From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/buf__sock_8cpp-source.html | 496 ++++++++++++++++++++++++++++ 1 file changed, 496 insertions(+) create mode 100644 docs/doxygen/nel/buf__sock_8cpp-source.html (limited to 'docs/doxygen/nel/buf__sock_8cpp-source.html') diff --git a/docs/doxygen/nel/buf__sock_8cpp-source.html b/docs/doxygen/nel/buf__sock_8cpp-source.html new file mode 100644 index 00000000..4e5f67e1 --- /dev/null +++ b/docs/doxygen/nel/buf__sock_8cpp-source.html @@ -0,0 +1,496 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# 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  
+

buf_sock.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2001 Nevrax Ltd.
+00008  *
+00009  * This file is part of NEVRAX NEL.
+00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00011  * it under the terms of the GNU General Public License as published by
+00012  * the Free Software Foundation; either version 2, or (at your option)
+00013  * any later version.
+00014 
+00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00018  * General Public License for more details.
+00019 
+00020  * You should have received a copy of the GNU General Public License
+00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00023  * MA 02111-1307, USA.
+00024  */
+00025 
+00026 #include "stdnet.h"
+00027 
+00028 #include "nel/misc/hierarchical_timer.h"
+00029 
+00030 #include "nel/net/buf_sock.h"
+00031 #include "nel/net/buf_server.h"
+00032 
+00033 #ifdef NL_OS_WINDOWS
+00034 #include <winsock2.h>
+00035 #elif defined NL_OS_UNIX
+00036 #include <netinet/in.h>
+00037 #endif
+00038 
+00039 using namespace NLMISC;
+00040 using namespace std;
+00041 
+00042 
+00043 namespace NLNET {
+00044 
+00045 
+00046 NLMISC::CMutex nettrace_mutex("nettrace_mutex");
+00047 
+00048 
+00049 /*
+00050  * Constructor
+00051  */
+00052 CBufSock::CBufSock( CTcpSock *sock ) :
+00053         SendNextValue(0),
+00054         ReceiveNextValue(0),
+00055         Sock( sock ),
+00056         _KnowConnected( false ),
+00057         _LastFlushTime( 0 ),
+00058         _TriggerTime( 20 ),
+00059         _TriggerSize( -1 ),
+00060         _RTSBIndex( 0 ),
+00061         _AppId( 0 ),
+00062         _ConnectedState( false )
+00063 {
+00064         nlnettrace( "CBufSock::CBufSock" ); // don't define a global object
+00065 
+00066         if ( Sock == NULL )
+00067           {
+00068                 Sock = new CTcpSock();
+00069           }
+00070 
+00071 #ifdef NL_DEBUG
+00072         _FlushTrigger = FTManual;
+00073 #endif
+00074         _LastFlushTime = CTime::getLocalTime();
+00075 }
+00076 
+00077 
+00078 /*
+00079  * Destructor
+00080  */
+00081 CBufSock::~CBufSock()
+00082 {
+00083         nlassert (this != InvalidSockId);       // invalid bufsock
+00084 
+00085         nlnettrace( "CBufSock::~CBufSock" );
+00086         
+00087         delete Sock; // the socket disconnects automatically if needed
+00088         
+00089         // destroy the structur to be sure that other people will not access to this anymore
+00090         AuthorizedCallback = "";
+00091         Sock = NULL;
+00092         _KnowConnected = false;
+00093         _LastFlushTime = 0;
+00094         _TriggerTime = 0;
+00095         _TriggerSize = 0;
+00096         _ReadyToSendBuffer.clear ();
+00097         _RTSBIndex = 0;
+00098         _AppId = 0;
+00099         _ConnectedState = false;
+00100 }
+00101 
+00102 
+00103 /*
+00104  * Returns a readable string from a vector of bytes, beginning from pos, limited to 'len' characters. '\0' are replaced by ' '
+00105  */
+00106 string stringFromVectorPart( const vector<uint8>& v, uint32 pos, uint32 len )
+00107 {
+00108         nlassertex( pos+len <= v.size(), ("pos=%u len=%u size=%u", pos, len, v.size()) );
+00109 
+00110         string s;
+00111         if ( (! v.empty()) && (len!=0) )
+00112         {
+00113                 // Copy contents
+00114                 s.resize( len );
+00115                 memcpy( &*s.begin(), &*v.begin()+pos, len );
+00116 
+00117                 // Replace '\0' characters
+00118                 string::iterator is;
+00119                 for ( is=s.begin(); is!=s.end(); ++is )
+00120                 {
+00121                         if ( ! isprint((uint8)(*is)) || (*is) == '%' )
+00122                         {
+00123                                 (*is) = '?';
+00124                         }
+00125                 }
+00126         }
+00127 
+00128         return s;
+00129 }
+00130 
+00131 
+00132 /*
+00133  * Force to send all data pending in the send queue
+00134  * Note: this method is used by clients (blocking sockets) and servers (non-blocking sockets)
+00135  * so it works in both cases.
+00136  * Precond: the send queue should not contain an empty block
+00137  */
+00138 bool CBufSock::flush()
+00139 {
+00140         nlassert (this != InvalidSockId);       // invalid bufsock
+00141         //nlnettrace( "CBufSock::flush" );
+00142 
+00143         // Copy data from the send queue to _ReadyToSendBuffer
+00144         TBlockSize netlen;
+00145 //      vector<uint8> tmpbuffer;
+00146 
+00147         // Process each element in the send queue
+00148         while ( ! SendFifo.empty() )
+00149         {
+00150                 uint8 *tmpbuffer;
+00151                 uint32 size;
+00152                 SendFifo.front( tmpbuffer, size );
+00153 
+00154                 // Compute the size and add it into the beginning of the buffer
+00155                 netlen = htonl( (TBlockSize)size );
+00156                 uint32 oldBufferSize = _ReadyToSendBuffer.size();
+00157                 _ReadyToSendBuffer.resize (oldBufferSize+sizeof(TBlockSize)+size);
+00158                 *(TBlockSize*)&(_ReadyToSendBuffer[oldBufferSize])=netlen;
+00159 
+00160                 // Append the temporary buffer to the global buffer
+00161                 CFastMem::memcpy (&_ReadyToSendBuffer[oldBufferSize+sizeof(TBlockSize)], tmpbuffer, size);
+00162                 SendFifo.pop();
+00163         }
+00164 
+00165         // Actual sending of _ReadyToSendBuffer
+00166         //if ( ! _ReadyToSendBuffer.empty() )
+00167         if ( _ReadyToSendBuffer.size() != 0 )
+00168         {               
+00169                 // Send
+00170                 CSock::TSockResult res;
+00171                 TBlockSize len = _ReadyToSendBuffer.size() - _RTSBIndex;
+00172 
+00173                 res = Sock->send( _ReadyToSendBuffer.getPtr()+_RTSBIndex, len, false );
+00174 
+00175                 if ( res == CSock::Ok )
+00176                 {
+00177 /*                      // Debug display
+00178                         switch ( _FlushTrigger )
+00179                         {
+00180                         case FTTime : nldebug( "LNETL1: Time triggered flush for %s:", asString().c_str() ); break;
+00181                         case FTSize : nldebug( "LNETL1: Size triggered flush for %s:", asString().c_str() ); break;
+00182                         default:          nldebug( "LNETL1: Manual flush for %s:", asString().c_str() );
+00183                         }
+00184                         _FlushTrigger = FTManual;
+00185                         nldebug( "LNETL1: %s sent effectively a buffer (%d on %d B)", asString().c_str(), len, _ReadyToSendBuffer.size() );
+00186 */                      
+00187                         
+00188                         // TODO OPTIM remove the nldebug for speed
+00189                         //commented for optimisation nldebug( "LNETL1: %s sent effectively %u/%u bytes (pos %u wantedsend %u)", asString().c_str(), len, _ReadyToSendBuffer.size(), _RTSBIndex, realLen/*, stringFromVectorPart(_ReadyToSendBuffer,_RTSBIndex,len).c_str()*/ );
+00190 
+00191                         if ( _RTSBIndex+len == _ReadyToSendBuffer.size() ) // for non-blocking mode (server)
+00192                         {
+00193                                 // If sending is ok, clear the global buffer
+00194                                 _ReadyToSendBuffer.clear();
+00195                                 _RTSBIndex = 0;
+00196                         }
+00197                         else
+00198                         {
+00199                                 // Or clear only the data that was actually sent
+00200                                 nlassertex( _RTSBIndex+len < _ReadyToSendBuffer.size(), ("index=%u len=%u size=%u", _RTSBIndex, len, _ReadyToSendBuffer.size()) );
+00201                                 _RTSBIndex += len;
+00202                                 if ( _ReadyToSendBuffer.size() > 20480 ) // if big, clear data already sent
+00203                                 {
+00204                                         uint nbcpy = _ReadyToSendBuffer.size() - len;
+00205                                         for (uint i = 0; i < nbcpy; i++)
+00206                                         {
+00207                                                 _ReadyToSendBuffer[i] = _ReadyToSendBuffer[i+len];
+00208                                         }
+00209                                         _ReadyToSendBuffer.resize(nbcpy);
+00210                                         //_ReadyToSendBuffer.erase( _ReadyToSendBuffer.begin(), _ReadyToSendBuffer.begin()+len );
+00211                                         _RTSBIndex = 0;
+00212                                 }
+00213                         }
+00214                 }
+00215                 else
+00216                 {
+00217 #ifdef NL_DEBUG
+00218                         // can happen in a normal behavior if, for example, the other side is not connect anymore
+00219                         nldebug( "LNETL1: %s failed to send effectively a buffer of %d bytes", asString().c_str(), _ReadyToSendBuffer.size() );
+00220 #endif
+00221                         return false;
+00222                 }
+00223         }
+00224 
+00225         return true;
+00226 }
+00227 
+00228 
+00229 /* Sets the time flush trigger (in millisecond). When this time is elapsed,
+00230  * all data in the send queue is automatically sent (-1 to disable this trigger)
+00231  */
+00232 void CBufSock::setTimeFlushTrigger( sint32 ms )
+00233 {
+00234         nlassert (this != InvalidSockId);       // invalid bufsock
+00235         _TriggerTime = ms;
+00236         _LastFlushTime = CTime::getLocalTime();
+00237 }
+00238 
+00239 
+00240 /*
+00241  * Update the network sending (call this method evenly). Returns false if an error occured.
+00242  */
+00243 bool CBufSock::update()
+00244 {
+00245         nlassert (this != InvalidSockId);       // invalid bufsock
+00246 //      nlnettrace( "CBufSock::update-BEGIN" );
+00247         // Time trigger
+00248 
+00249         if ( _TriggerTime != -1 )
+00250         {
+00251                 TTime now = CTime::getLocalTime();
+00252                 if ( (sint32)(now-_LastFlushTime) >= _TriggerTime )
+00253                 {
+00254 #ifdef NL_DEBUG
+00255                         _FlushTrigger = FTTime;
+00256 #endif
+00257                         if ( flush() )
+00258                         {
+00259                                 _LastFlushTime = now;
+00260 //                              nlnettrace ( "CBufSock::update-END time 1" );
+00261                                 return true;
+00262                         }
+00263                         else
+00264                         {
+00265 //                              nlnettrace ( "CBufSock::update-END time 0" );
+00266                                 return false;
+00267                         }
+00268                 }
+00269         }
+00270         // Size trigger
+00271         if ( _TriggerSize != -1 )
+00272         {
+00273                 if ( (sint32)SendFifo.size() > _TriggerSize )
+00274                 {
+00275 #ifdef NL_DEBUG
+00276                         _FlushTrigger = FTSize;
+00277 #endif
+00278 //                      nlnettrace( "CBufSock::update-END size" );
+00279                         return flush();
+00280                 }
+00281         }
+00282 //      nlnettrace( "CBufSock::update-END nosend" );
+00283         return true;
+00284 }
+00285 
+00286 
+00287 /*
+00288  * Connects to the specified addr; set connectedstate to true if no connection advertising is needed
+00289  * Precond: not connected
+00290  */
+00291 void CBufSock::connect( const CInetAddress& addr, bool nodelay, bool connectedstate )
+00292 {
+00293         nlassert (this != InvalidSockId);       // invalid bufsock
+00294         nlassert( ! Sock->connected() );
+00295 
+00296         SendNextValue = ReceiveNextValue = 0;
+00297         
+00298         Sock->connect( addr );
+00299         _ConnectedState = connectedstate;
+00300         _KnowConnected = connectedstate;
+00301         if ( nodelay )
+00302         {
+00303                 Sock->setNoDelay( true );
+00304         }
+00305 }
+00306 
+00307 
+00308 /*
+00309  * Disconnects; set connectedstate to false if no disconnection advertising is needed
+00310  */
+00311 void CBufSock::disconnect( bool connectedstate )
+00312 {
+00313         nlassert (this != InvalidSockId);       // invalid bufsock
+00314         Sock->disconnect();
+00315         _ConnectedState = connectedstate;
+00316         _KnowConnected = connectedstate;
+00317 
+00318         SendNextValue = ReceiveNextValue = 0;
+00319 }
+00320 
+00321 
+00322 /*
+00323  * Returns a string with the characteristics of the object
+00324  */
+00325 string CBufSock::asString() const
+00326 {
+00327         stringstream ss;
+00328         if (this == InvalidSockId) // tricky
+00329                 ss << "<Null>";
+00330         else
+00331         {
+00332                 // if it crashs here, it means that the CBufSock was deleted and you try to access to the virtual table that is empty
+00333                 // because the object is destroyed.
+00334                 ss << typeStr();
+00335                 ss << hex << this << dec << " (socket ";
+00336                 
+00337                 if (Sock == NULL)
+00338                         ss << "<Null>";
+00339                 else
+00340                         ss << Sock->descriptor();
+00341 
+00342                 ss << ")";
+00343         }
+00344         return ss.str();
+00345 }
+00346 
+00347 
+00348 /*
+00349  * Constructor with an existing socket (created by an accept())
+00350  */
+00351 CServerBufSock::CServerBufSock( CTcpSock *sock ) :
+00352         CBufSock( sock ),
+00353         _Advertised( false ),
+00354         _NowReadingBuffer( false ),
+00355         _BytesRead( 0 ),
+00356         _Length( 0 ),
+00357         _OwnerTask( NULL )
+00358 {
+00359         nlassert (this != InvalidSockId);       // invalid bufsock
+00360         nlnettrace( "CServerBufSock::CServerBufSock" );
+00361 }
+00362 
+00363 
+00364 // In Receive Threads:
+00365 
+00366 
+00367 /*
+00368  * Receives a part of a message (nonblocking socket only)
+00369  */
+00370 bool CServerBufSock::receivePart()
+00371 {
+00372         nlassert (this != InvalidSockId);       // invalid bufsock
+00373         nlnettrace( "CServerBufSock::receivePart" );
+00374 
+00375         TBlockSize actuallen;
+00376         if ( ! _NowReadingBuffer )
+00377         {
+00378                 // Receiving length prefix
+00379                 actuallen = sizeof(_Length)-_BytesRead;
+00380                 Sock->receive( (uint8*)(&_Length)+_BytesRead, actuallen );
+00381                 _BytesRead += actuallen;
+00382                 if ( _BytesRead == sizeof(_Length ) )
+00383                 {
+00384                         if ( _Length != 0 )
+00385                         {
+00386                                 _Length = ntohl( _Length );
+00387 
+00388                                 // Test size limit
+00389                                 if ( _Length > _OwnerTask->server()->maxExpectedBlockSize() )
+00390                                 {
+00391                                         nlwarning( "LNETL1: Socket %s received length exceeding max expected, in block header... Disconnecting", asString().c_str() );
+00392                                         throw ESocket( "Received length exceeding max expected", false );
+00393                                 }
+00394 
+00395                                 _NowReadingBuffer = true;
+00396                                 _ReceiveBuffer.resize( _Length );
+00397                         }
+00398                         else
+00399                         {
+00400                                 nlwarning( "LNETL1: Socket %s received null length in block header", asString().c_str() );
+00401                         }
+00402                         _BytesRead = 0;
+00403                 }
+00404         }
+00405 
+00406         if ( _NowReadingBuffer )
+00407         {
+00408                 // Receiving payload buffer
+00409                 actuallen = _Length-_BytesRead;
+00410                 Sock->receive( &*_ReceiveBuffer.begin()+_BytesRead, actuallen );
+00411                 _BytesRead += actuallen;
+00412 
+00413                 if ( _BytesRead == _Length )
+00414                 {
+00415 #ifdef NL_DEBUG
+00416                         nldebug( "LNETL1: %s received buffer (%u bytes): [%s]", asString().c_str(), _ReceiveBuffer.size(), stringFromVector(_ReceiveBuffer).c_str() );
+00417 #endif
+00418                         _NowReadingBuffer = false;
+00419                         _BytesRead = 0;
+00420                         return true;
+00421                 }
+00422         }
+00423 
+00424         return false;
+00425 }
+00426 
+00427 } // NLNET
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1