# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

udp_sim_sock.cpp

Go to the documentation of this file.
00001 
00008 /* Copyright, 2002 Nevrax Ltd.
00009  *
00010  * This file is part of NEVRAX NEL.
00011  * NEVRAX NEL is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2, or (at your option)
00014  * any later version.
00015 
00016  * NEVRAX NEL is distributed in the hope that it will be useful, but
00017  * WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00019  * General Public License for more details.
00020 
00021  * You should have received a copy of the GNU General Public License
00022  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00023  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00024  * MA 02111-1307, USA.
00025  */
00026 
00027 #include "stdnet.h"
00028 
00029 #include <queue>
00030 
00031 #include "nel/misc/config_file.h"
00032 
00033 #include "nel/net/udp_sock.h"
00034 #include "nel/net/udp_sim_sock.h"
00035 
00036 using namespace std;
00037 using namespace NLMISC;
00038 
00039 namespace NLNET {
00040 
00041 //
00042 // Class
00043 //
00044 
00045 struct CBufferizedOutPacket
00046 {
00047         CBufferizedOutPacket (CUdpSock *client, const uint8 *packet, uint32 packetSize, uint32 delay, const CInetAddress *addr):
00048                 Client(client), PacketSize(packetSize), Time(CTime::getLocalTime()+delay)
00049         {
00050                 nlassert (packetSize > 0);
00051                 nlassert (packet != NULL);
00052                 nlassert (client != NULL);
00053 
00054                 Packet = new uint8[packetSize];
00055                 memcpy (Packet, packet, packetSize);
00056 
00057                 if (addr != NULL)
00058                 {
00059                         Addr = new CInetAddress;
00060                         *Addr = *addr;
00061                 }
00062                 else
00063                 {
00064                         Addr = NULL;
00065                 }
00066         }
00067 
00068         ~CBufferizedOutPacket ()
00069         {
00070                 nlassert (Packet != NULL);
00071                 delete [] Packet;
00072                 Packet = NULL;
00073                 Client = NULL;
00074                 PacketSize = 0;
00075                 Time = 0;
00076                 if (Addr != NULL)
00077                         delete Addr;
00078         }
00079 
00080         CUdpSock                *Client;
00081         uint8                   *Packet;
00082         uint32                   PacketSize;
00083         TTime                    Time;
00084         CInetAddress    *Addr;
00085 };
00086 
00087 
00088 //
00089 // Variables
00090 //
00091 
00092 static queue<CBufferizedOutPacket*> BufferizedOutPackets;
00093 static queue<CBufferizedOutPacket*> BufferizedInPackets;
00094 
00095 uint32  CUdpSimSock::_InLag = 0;
00096 uint8   CUdpSimSock::_InPacketLoss = 0;
00097 
00098 uint32  CUdpSimSock::_OutLag = 0;
00099 uint8   CUdpSimSock::_OutPacketLoss = 0;
00100 uint8   CUdpSimSock::_OutPacketDuplication = 0;
00101 uint8   CUdpSimSock::_OutPacketDisordering = 0;
00102 
00103 //
00104 // Functions
00105 //
00106 
00107 void CUdpSimSock::sendUDPNow (const uint8 *buffer, uint32 len, const CInetAddress *addr)
00108 {
00109         if (addr == NULL)
00110                 UdpSock.send (buffer, len);
00111         else
00112                 UdpSock.sendTo (buffer, len, *addr);
00113 }
00114 
00115 void CUdpSimSock::sendUDP (const uint8 *buffer, uint32& len, const CInetAddress *addr)
00116 {
00117         nlassert (buffer != NULL);
00118         nlassert (len > 0);
00119 
00120         if ((float)rand()/(float)(RAND_MAX)*100.0f >= _OutPacketLoss)
00121         {
00122                 sint32 lag = _OutLag /*+ (rand()%40) - 20*/;// void disordering
00123                 
00124                 if (lag > 100)
00125                 {
00126                         // send the packet later
00127 
00128                         CBufferizedOutPacket *bp = new CBufferizedOutPacket (&UdpSock, buffer, len, lag, addr);
00129 
00130                         // duplicate the packet
00131                         if ((float)rand()/(float)(RAND_MAX)*100.0f < _OutPacketDisordering && BufferizedOutPackets.size() > 0)
00132                         {
00133                                 CBufferizedOutPacket *bp2 = BufferizedOutPackets.back();
00134 
00135                                 // exange the time
00136                                 TTime t = bp->Time;
00137                                 bp->Time = bp2->Time;
00138                                 bp2->Time = t;
00139 
00140                                 // exange packet in the buffer
00141                                 BufferizedOutPackets.back() = bp;
00142                                 bp = bp2;
00143                         }
00144 
00145                         BufferizedOutPackets.push (bp);
00146 
00147                         // duplicate the packet
00148                         if ((float)rand()/(float)(RAND_MAX)*100.0f < _OutPacketDuplication)
00149                         {
00150                                 CBufferizedOutPacket *bp = new CBufferizedOutPacket (&UdpSock, buffer, len, lag, addr);
00151                                 BufferizedOutPackets.push (bp);
00152                         }
00153                 }
00154                 else
00155                 {
00156                         // send the packet NOW
00157 
00158                         sendUDPNow (buffer, len, addr);
00159 
00160                         // duplicate the packet
00161                         if ((float)rand()/(float)(RAND_MAX)*100.0f < _OutPacketDuplication)
00162                         {
00163                                 sendUDPNow (buffer, len, addr);
00164                         }
00165                 }
00166         }
00167 }
00168 
00169 
00170 
00171 void CUdpSimSock::updateBufferizedPackets ()
00172 {
00173         TTime ct = CTime::getLocalTime ();
00174         while (!BufferizedOutPackets.empty())
00175         {
00176                 CBufferizedOutPacket *bp = BufferizedOutPackets.front ();
00177                 if (bp->Time <= ct)
00178                 {
00179                         // time to send the message
00180                         sendUDPNow (bp->Packet, bp->PacketSize, bp->Addr);
00181                         delete bp;
00182                         BufferizedOutPackets.pop ();
00183                 }
00184                 else
00185                 {
00186                         break;
00187                 }
00188         }
00189 }
00190 
00191 void                            cbSimVar (CConfigFile::CVar &var)
00192 {
00193              if (var.Name == "SimInLag") CUdpSimSock::_InLag = var.asInt ();
00194         else if (var.Name == "SimInPacketLost") CUdpSimSock::_InPacketLoss = var.asInt ();
00195         else if (var.Name == "SimOutLag") CUdpSimSock::_OutLag = var.asInt ();
00196         else if (var.Name == "SimOutPacketLost") CUdpSimSock::_OutPacketLoss = var.asInt ();
00197         else if (var.Name == "SimOutPacketDuplication") CUdpSimSock::_OutPacketDuplication = var.asInt ();
00198         else if (var.Name == "SimOutPacketDisordering") CUdpSimSock::_OutPacketDisordering = var.asInt ();
00199         else nlstop;
00200 }
00201 
00202 void                            CUdpSimSock::setSimValues (NLMISC::CConfigFile &cf)
00203 {
00204         cf.setCallback ("SimInLag", cbSimVar);
00205         cf.setCallback ("SimInPacketLost", cbSimVar);
00206         cf.setCallback ("SimOutLag", cbSimVar);
00207         cf.setCallback ("SimOutPacketLost", cbSimVar);
00208         cf.setCallback ("SimOutPacketDuplication", cbSimVar);
00209         cf.setCallback ("SimOutPacketDisordering", cbSimVar);
00210         
00211         try
00212         {
00213                 cbSimVar (cf.getVar("SimInLag"));
00214                 cbSimVar (cf.getVar("SimInPacketLost"));
00215                 cbSimVar (cf.getVar("SimOutLag"));
00216                 cbSimVar (cf.getVar("SimOutPacketLost"));
00217                 cbSimVar (cf.getVar("SimOutPacketDuplication"));
00218                 cbSimVar (cf.getVar("SimOutPacketDisordering"));
00219         }
00220         catch (Exception &e)
00221         {
00222                 nlwarning ("Problem during getting Sim values from config file: %s", e.what());
00223         }
00224 }
00225 
00226 void                            CUdpSimSock::connect( const CInetAddress& addr )
00227 {
00228         UdpSock.connect (addr);
00229 }
00230 
00231 void                            CUdpSimSock::close()
00232 {
00233         UdpSock.close ();
00234 }
00235 
00236 uint8 buffer [10000];
00237 
00238 bool                            CUdpSimSock::dataAvailable ()
00239 {
00240         updateBufferizedPackets ();
00241 
00242         if (_InLag > 0)
00243         {
00244                 while (UdpSock.dataAvailable ())
00245                 {
00246                         CInetAddress addr;
00247                         uint len = 10000;
00248                         UdpSock.receivedFrom (buffer, len, addr);
00249 
00250                         if ((float)rand()/(float)(RAND_MAX)*100.0f >= _InPacketLoss)
00251                         {
00252                                 CBufferizedOutPacket *bp = new CBufferizedOutPacket (&UdpSock, buffer, len, _InLag, &addr);
00253                                 BufferizedInPackets.push (bp);
00254                         }
00255                 }
00256 
00257                 TTime ct = CTime::getLocalTime ();
00258                 if (!BufferizedInPackets.empty() && BufferizedInPackets.front ()->Time <= ct)
00259                         return true;
00260                 else
00261                         return false;
00262         }
00263         else
00264         {
00265                 return UdpSock.dataAvailable ();
00266         }
00267 }
00268 
00269 bool                            CUdpSimSock::receive (uint8 *buffer, uint32& len, bool throw_exception)
00270 {
00271         if (_InLag> 0)
00272         {
00273                 if (BufferizedInPackets.empty())
00274                 {
00275                         if (throw_exception)
00276                                 throw Exception ("no data available");
00277                         return false;
00278                 }
00279                 
00280                 CBufferizedOutPacket *bp = BufferizedInPackets.front ();
00281                 uint32 s = min (len, bp->PacketSize);
00282                 memcpy (buffer, bp->Packet, s);
00283                 len = s;
00284 
00285                 delete bp;
00286                 BufferizedInPackets.pop ();
00287                 return true;
00288         }
00289         else
00290         {
00291                 return UdpSock.receive(buffer, len, throw_exception);
00292         }
00293 }
00294 
00295 CSock::TSockResult      CUdpSimSock::send (const uint8 *buffer, uint32& len, bool throw_exception)
00296 {
00297         sendUDP (buffer, len);
00298         return CSock::Ok;
00299 }
00300         
00301 void CUdpSimSock::sendTo (const uint8 *buffer, uint32& len, const CInetAddress& addr)
00302 {
00303         sendUDP (buffer, len, &addr);
00304 }
00305 
00306 bool                            CUdpSimSock::connected()
00307 {
00308         return UdpSock.connected ();
00309 }
00310 
00311 } // NLNET