Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | Related Pages

networking.cpp

00001 /***************************************************************************
00002                         networking.cpp  -  description
00003                                 -------------------
00004     begin                : jeu dec 23 2004
00005     copyright            : (C) 2004-2006 by Duong-Khang NGUYEN
00006     email                : neoneurone @ users sourceforge net
00007 
00008     $Id: networking.cpp 11 2006-06-25 11:47:22Z neoneurone $
00009  ***************************************************************************/
00010 
00011 /***************************************************************************
00012  *                                                                         *
00013  *   This program is free software; you can redistribute it and/or modify  *
00014  *   it under the terms of the GNU General Public License as published by  *
00015  *   the Free Software Foundation; either version 2 of the License, or     *
00016  *   any later version.                                                    *
00017  *                                                                         *
00018  ***************************************************************************/
00019 
00020 #include "netnode.h"
00021 #include "networking.h"
00022 
00023 
00024    /*=====================================================================*/
00025 Networking::Networking():
00026 networkingCode( OC_NET_UNDEFINED ),
00027 pSocketSet( NULL ),
00028 pServerSocket( NULL )
00029 {
00030     OPENCITY_DEBUG("ctor");
00031 
00032     boolNetworkInitialized = (SDLNet_Init() != -1);
00033     if (boolNetworkInitialized == false) {
00034         cerr << "WARNING: I couldn't initialize networking. "
00035              << "The error was: " << SDLNet_GetError() << endl;
00036     }
00037 }
00038 
00039 
00040    /*=====================================================================*/
00041 Networking::~Networking()
00042 {
00043     OPENCITY_DEBUG("dtor");
00044 
00045     //FIXME: free server ressources
00046 
00047     if (boolNetworkInitialized == true) {
00048         SDLNet_Quit();
00049         boolNetworkInitialized = false;
00050         networkingCode = OC_NET_UNDEFINED;
00051         pServerSocket = NULL;
00052     }
00053 }
00054 
00055 
00056    /*=====================================================================*/
00057 const string
00058 Networking::GetClientHost(
00059     const uint index )
00060 {
00061     assert( index < this->vClient.size() );
00062     return (string)(SDLNet_ResolveIP(&vClient[index].ip));
00063 }
00064 
00065 
00066    /*=====================================================================*/
00067 const uint
00068 Networking::GetClientNum()
00069 {
00070     return this->vClient.size();
00071 }
00072 
00073 
00074    /*=====================================================================*/
00075 const uint
00076 Networking::GetClientMax()
00077 {
00078     return OC_NET_CLIENT_MAX;
00079 }
00080 
00081 
00082    /*=====================================================================*/
00083 const OPENCITY_NET_CODE
00084 Networking::GetMachineRole()
00085 {
00086     return this->networkingCode;
00087 }
00088 
00089 
00090    /*=====================================================================*/
00091 const uint
00092 Networking::GetPingTimeout()
00093 {
00094     return OC_NET_PING_TIMEOUT;
00095 }
00096 
00097 
00098    /*=====================================================================*/
00099 const uint
00100 Networking::GetServerNum()
00101 {
00102     //TODO: STUB
00103     OPENCITY_DEBUG("TODO");
00104     assert(0);
00105     return 0;
00106 }
00107 
00108 
00109    /*=====================================================================*/
00110 const string
00111 Networking::GetServerHost( const uint index )
00112 {
00113     //TODO: STUB
00114     OPENCITY_DEBUG("TODO");
00115     assert(0);
00116     return "";
00117 }
00118 
00119 
00120    /*=====================================================================*/
00121 const string
00122 Networking::GetVersion()
00123 {
00124     return VERSION;
00125 }
00126 
00127 
00128    /*=====================================================================*/
00129 const string
00130 Networking::GetProtocol()
00131 {
00132     return OC_NET_PROTOCOL;
00133 }
00134 
00135 
00136    /*=====================================================================*/
00137 const OPENCITY_NET_CODE
00138 Networking::Accept( uint & rid )
00139 {
00140 // IF the networking is not init THEN error
00141     if (this->boolNetworkInitialized == false)
00142         return OC_NET_ERROR;
00143 
00144 // IF the server is not running THEN error
00145     if (this->pServerSocket == NULL)
00146         return OC_NET_SERVER_STOPED;
00147 
00148 // IF the server is full THEN error
00149 //  if (this->vClient.size() == OC_NET_CLIENT_MAX)
00150 //      return OC_NET_SERVER_FULL;
00151 
00152 // Create the new socket to handle the client
00153     Netnode nodeClient;
00154     nodeClient.socket = SDLNet_TCP_Accept(this->pServerSocket);
00155     if (nodeClient.socket != NULL) {
00156         NetMessage msg;
00157     // Put the client socket into the server's socket set for future use
00158         if (SDLNet_TCP_AddSocket( this->pSocketSet, nodeClient.socket ) == -1) {
00159         // Send NCK
00160             msg.cmd = OC_NET_NCK;
00161             (void)SDLNet_TCP_Send(nodeClient.socket, &msg, sizeof(NetMessage));
00162             SDLNet_TCP_Close(nodeClient.socket);
00163             rid = 0;
00164 
00165             return OC_NET_SERVER_FULL;
00166         }
00167         else {
00168             nodeClient.ip = *(SDLNet_TCP_GetPeerAddress(nodeClient.socket));
00169             vClient.push_back(nodeClient);
00170             rid = vClient.size()-1;
00171 
00172         // Send ACK
00173             msg.cmd = OC_NET_ACK;
00174             this->SendMessage( msg, rid );
00175         }
00176     }
00177     else {
00178         rid = 0;
00179         return OC_NET_NOCLIENT;
00180     }
00181 
00182     return OC_NET_OK;
00183 }
00184 
00185 
00186    /*=====================================================================*/
00187 const OPENCITY_NET_CODE
00188 Networking::Reject( const uint id )
00189 {
00190     OPENCITY_DEBUG( "TODO" );
00191     assert( 0 );
00192     return OC_NET_ERROR;
00193 }
00194 
00195 
00196    /*=====================================================================*/
00197 const OPENCITY_NET_CODE
00198 Networking::StartServer( const OC_SUINT port )
00199 {
00200 // IF the server is already running THEN error
00201     if (pServerSocket != NULL) {
00202         return OC_NET_SERVER_STARTED;
00203     }
00204 
00205     IPaddress ip;
00206 
00207     if (SDLNet_ResolveHost(&ip, NULL, port) == -1) {
00208         cerr << "ERROR: I couldn't start the server: "
00209              << SDLNet_GetError() << endl;
00210         return OC_NET_ERROR;
00211     }
00212 
00213     this->pServerSocket = SDLNet_TCP_Open(&ip);
00214     if (pServerSocket == NULL) {
00215         cerr << "ERROR: I couldn't open the server's socket: "
00216              << SDLNet_GetError() << endl;
00217         return OC_NET_ERROR;
00218     }
00219 
00220 // Allocate the socket set for the server
00221     this->pSocketSet = SDLNet_AllocSocketSet(OC_NET_CLIENT_MAX);
00222     if (this->pSocketSet == NULL) {
00223         cerr << "ERROR: I couldn't allocate a socket set: "
00224              << SDLNet_GetError() << endl;
00225         return OC_NET_ERROR;
00226     }
00227 
00228     return OC_NET_OK;
00229 }
00230 
00231 
00232    /*=====================================================================*/
00233 const OPENCITY_NET_CODE
00234 Networking::StopServer()
00235 {
00236 // IF the server is not running THEN error
00237     if (pServerSocket == NULL) {
00238         return OC_NET_SERVER_STOPED;
00239     }
00240 
00241     SDLNet_TCP_Close(this->pServerSocket);
00242     pServerSocket = NULL;
00243 
00244     SDLNet_FreeSocketSet(this->pSocketSet);
00245     this->pSocketSet = NULL;
00246 
00247     return OC_NET_OK;
00248 }
00249 
00250 
00251    /*=====================================================================*/
00252 const OPENCITY_NET_CODE
00253 Networking::ProcessServerData()
00254 {
00255     uint id;
00256     OPENCITY_NET_CODE netCode;
00257     NetMessage msg;
00258     ClientIter i;
00259     int recv;
00260     std::vector<ClientIter> vToClose;
00261 
00262 // Accept an incoming connection and automatically ACK
00263     netCode = this->Accept( id );
00264     if (netCode == OC_NET_OK) {
00265         OPENCITY_DEBUG( "New number of clients: " << this->GetClientNum() );
00266     }
00267     else if (netCode == OC_NET_SERVER_FULL) {
00268         OPENCITY_DEBUG( "Server is full, new connection rejected" );
00269     }
00270 
00271 // Check socket set for activity
00272 // Otherwise return
00273     if (SDLNet_CheckSockets( this->pSocketSet, OC_NET_CHECK_TIMEOUT ) < 1)
00274         return OC_NET_OK;
00275 
00276 // Process waiting messages sent by client
00277     OPENCITY_DEBUG( "Begin reading socket" );
00278     for (i = this->vClient.begin(); i != this->vClient.end(); i++) {
00279         if (SDLNet_SocketReady((*i).socket) != 0) {
00280             recv = SDLNet_TCP_Recv((*i).socket, &msg, sizeof(NetMessage) );
00281 
00282             if (recv > 0) {
00283             // Disconnect request ?
00284                 if (msg.cmd == OC_NET_DNT) {
00285                     OPENCITY_DEBUG( "One client disconnected." );
00286                 // FIXME: send ACK
00287                     vToClose.push_back( i );
00288                 }
00289             }
00290             else {
00291                 OPENCITY_DEBUG( "No data received or error. Closing client socket." );
00292                 vToClose.push_back( i );
00293             }
00294         }
00295     }
00296     OPENCITY_DEBUG( "End reading socket" );
00297 
00298     uint c;
00299     for ( c = 0; c < vToClose.size(); c++ ) {
00300         this->Close(vToClose[c]);
00301     }
00302 
00303     return OC_NET_OK;
00304 }
00305 
00306 
00307    /*=====================================================================*/
00308 const OPENCITY_NET_CODE
00309 Networking::Open(
00310     const string serverHost,
00311     const OC_SUINT port )
00312 {
00313 // IF we are already connected THEN
00314     if (this->pServerSocket != NULL)
00315         return OC_NET_CLIENT_CONNECTED;
00316 
00317 // IF we can not resolve the host THEN error
00318     IPaddress ip;
00319     if (SDLNet_ResolveHost(&ip, serverHost.c_str(), port) == -1) {
00320         cerr << "ERROR: I couldn't resolve the server name: "
00321              << SDLNet_GetError() << endl;
00322         return OC_NET_ERROR;
00323     }
00324 
00325 // Open the server socket
00326     this->pServerSocket = SDLNet_TCP_Open(&ip);
00327     if (pServerSocket == NULL) {
00328         cerr << "ERROR: I couldn't connect to the server: "
00329              << SDLNet_GetError() << endl;
00330         return OC_NET_ERROR;
00331     }
00332 
00333 // Reading ACK/NCK
00334     NetMessage msg;
00335     OPENCITY_NET_CODE nc = OC_NET_OK;
00336     if (this->Receive( &msg, sizeof(NetMessage) ) == OC_NET_OK) {
00337         switch (msg.cmd) {
00338         case OC_NET_ACK:
00339             nc = OC_NET_CLIENT_ACCEPTED;
00340             break;
00341 
00342         case OC_NET_NCK:
00343         // Close the socket
00344             SDLNet_TCP_Close(this->pServerSocket);
00345             this->pServerSocket = NULL;
00346             nc = OC_NET_CLIENT_REJECTED;
00347             break;
00348 
00349         default:
00350             nc = OC_NET_ERROR;
00351         }
00352     }
00353 
00354     return nc;
00355 }
00356 
00357 
00358    /*=====================================================================*/
00359 const OPENCITY_NET_CODE
00360 Networking::Close()
00361 {
00362     NetMessage msg;
00363     OPENCITY_NET_CODE netCode;
00364 
00365 // Send disconnect command
00366     msg.cmd = OC_NET_DNT;
00367     netCode = SendMessage( msg );
00368 
00369 // Close the socket
00370     SDLNet_TCP_Close(this->pServerSocket);
00371     this->pServerSocket = NULL;
00372 
00373     return netCode;
00374 }
00375 
00376 
00377    /*=====================================================================*/
00378 const OPENCITY_NET_CODE
00379 Networking::Close( ClientIter i )
00380 {
00381 //  assert( i != NULL );
00382 
00383 //TODO: send the "disconnect" command to the client
00384 
00385 // Remove the socket from the set
00386     (void)SDLNet_TCP_DelSocket( this->pSocketSet, (*i).socket );
00387 
00388 // Close the client socket
00389     SDLNet_TCP_Close((*i).socket);
00390     (*i).socket = NULL;
00391 
00392 // Erase the client from the vector
00393     this->vClient.erase(i);
00394 //  std::remove( i, i, (*i) );
00395 
00396     return OC_NET_OK;
00397 }
00398 
00399 
00400    /*=====================================================================*/
00401 const OPENCITY_NET_CODE
00402 Networking::Send(
00403     const void* const data,
00404     const uint len )
00405 {
00406     static uint sent;
00407 
00408 // IF we are not connected THEN error
00409     if (this->pServerSocket == NULL)
00410         return OC_NET_CLIENT_NOTCONNECTED;
00411 
00412 // IF there is no data to send THEN error
00413     if (len == 0)
00414         return OC_NET_NODATA;
00415 
00416     sent = SDLNet_TCP_Send(this->pServerSocket, const_cast<void*>(data), len);
00417     if (sent != len) {
00418         OPENCITY_DEBUG("ERROR: Net send");
00419         return OC_NET_SENDERROR;
00420     }
00421 
00422     return OC_NET_OK;
00423 }
00424 
00425 
00426    /*=====================================================================*/
00427 const OPENCITY_NET_CODE
00428 Networking::Send(
00429     const void* const data,
00430     const uint len,
00431     const uint cid )
00432 {
00433     static uint sent;
00434 
00435 // WARNING: the code is similar to the Send() method
00436     assert( cid < this->vClient.size() );
00437 
00438 // IF there is no data to send THEN error
00439     if (len == 0)
00440         return OC_NET_NODATA;
00441 
00442     sent = SDLNet_TCP_Send(this->vClient[cid].socket, const_cast<void*>(data), len);
00443     if (sent != len) {
00444         OPENCITY_DEBUG("ERROR: Net send");
00445         return OC_NET_SENDERROR;
00446     }
00447 
00448     return OC_NET_OK;
00449 }
00450 
00451 
00452    /*=====================================================================*/
00453 const OPENCITY_NET_CODE
00454 Networking::SendMessage( NetMessage & rMsg )
00455 {
00456 // IF we are not connected THEN
00457     if (this->pServerSocket == NULL)
00458         return OC_NET_CLIENT_NOTCONNECTED;
00459 
00460 // Send the message to the node
00461     rMsg.dataLength = OC_NET_DATA_LENGTH;       // hack
00462     return this->Send( &rMsg, sizeof(NetMessage) );
00463 }
00464 
00465 
00466    /*=====================================================================*/
00467 const OPENCITY_NET_CODE
00468 Networking::SendMessage(
00469     NetMessage & rMsg,
00470     const uint cid )
00471 {
00472 // Send the message to the node
00473     rMsg.dataLength = OC_NET_DATA_LENGTH;       // hack
00474     return this->Send( &rMsg, sizeof(NetMessage), cid );
00475 }
00476 
00477 
00478    /*=====================================================================*/
00479 const OPENCITY_NET_CODE
00480 Networking::Receive(
00481     void* const data,
00482     const uint maxlen )
00483 {
00484     static int recv;
00485 
00486 // IF we are not connected THEN error
00487     if (this->pServerSocket == NULL)
00488         return OC_NET_CLIENT_NOTCONNECTED;
00489 
00490 // IF the buffer is not big enough THEN
00491     if (maxlen == 0)
00492         return OC_NET_BUFFERROR;
00493 
00494     recv = SDLNet_TCP_Recv( this->pServerSocket, data, maxlen );
00495     if (recv <= 0) {
00496         OPENCITY_DEBUG("WARNING: no data received or error");
00497         return OC_NET_RECVERROR;
00498     }
00499 
00500     return OC_NET_OK;
00501 }
00502 
00503 
00504    /*=====================================================================*/
00505 const OPENCITY_NET_CODE
00506 Networking::ReceiveMessage(
00507     NetMessage & rMsg )
00508 {
00509 // IF we are not connected THEN
00510     if (this->pServerSocket == NULL)
00511         return OC_NET_CLIENT_NOTCONNECTED;
00512 
00513 // Wait for the commands sent by the server
00514     return this->Receive( &rMsg, sizeof(NetMessage) );
00515 }
00516 
00517 
00518    /*=====================================================================*/
00519 const OPENCITY_NET_CODE
00520 Networking::Receive(
00521     void* const data,
00522     const uint maxlen,
00523     const uint cid )
00524 {
00525     static int recv;
00526 
00527 // WARNING: the code is similar to the client's Receive() method
00528     assert( cid < this->vClient.size() );
00529 
00530 // IF the buffer is not big enough THEN
00531     if (maxlen == 0)
00532         return OC_NET_BUFFERROR;
00533 
00534     recv = SDLNet_TCP_Recv( this->vClient[cid].socket, data, maxlen );
00535     if (recv <= 0) {
00536         return OC_NET_NODATA;
00537     }
00538 
00539     return OC_NET_OK;
00540 }
00541 
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552 

Generated on Sat Nov 11 10:21:10 2006 for OpenCity by  doxygen 1.4.2