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/sock_8cpp-source.html | 663 +++++++++++++++++++++++++++++++++ 1 file changed, 663 insertions(+) create mode 100644 docs/doxygen/nel/sock_8cpp-source.html (limited to 'docs/doxygen/nel/sock_8cpp-source.html') diff --git a/docs/doxygen/nel/sock_8cpp-source.html b/docs/doxygen/nel/sock_8cpp-source.html new file mode 100644 index 00000000..b6394c1d --- /dev/null +++ b/docs/doxygen/nel/sock_8cpp-source.html @@ -0,0 +1,663 @@ + + + + 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  
+

sock.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2000 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/net/sock.h"
+00029 #include "nel/misc/time_nl.h"
+00030 
+00031 #ifdef NL_OS_WINDOWS
+00032 
+00033 #       include <winsock2.h>
+00034 //#     include <windows.h>
+00035 #       define socklen_t int
+00036 #       define ERROR_NUM WSAGetLastError()
+00037 #       define ERROR_WOULDBLOCK WSAEWOULDBLOCK
+00038 
+00039 #elif defined NL_OS_UNIX
+00040 
+00041 #       include <unistd.h>
+00042 #       include <sys/types.h>
+00043 #       include <sys/time.h>
+00044 #       include <sys/socket.h>
+00045 #       include <netinet/in.h>
+00046 #       include <netinet/tcp.h>
+00047 #       include <arpa/inet.h>
+00048 #       include <netdb.h>
+00049 #       include <fcntl.h>
+00050 #       include <errno.h>
+00051 #       define SOCKET_ERROR -1
+00052 #       define INVALID_SOCKET -1
+00053 #       define ERROR_NUM errno
+00054 #       define ERROR_WOULDBLOCK EWOULDBLOCK
+00055 #       define ERROR_MSG strerror(errno)
+00056 typedef int SOCKET;
+00057 
+00058 #endif
+00059 
+00060 using namespace std;
+00061 using namespace NLMISC;
+00062 
+00063 namespace NLNET {
+00064 
+00065 
+00066 bool CSock::_Initialized = false;
+00067 
+00068 long CSock::_TimeoutS = 0;
+00069 
+00070 long CSock::_TimeoutMs = 0;
+00071 
+00072 
+00073 /*
+00074  * ESocket constructor
+00075  */
+00076 ESocket::ESocket( const char *reason, bool systemerror, CInetAddress *addr )
+00077 {
+00078 /*it doesnt work on linux, should do something more cool
+00079         std::stringstream ss;
+00080         ss << "Socket error: " << reason;
+00081         if ( systemerror )
+00082         {
+00083                 ss << " (" << ERROR_NUM;
+00084 #ifdef NL_OS_UNIX
+00085                 ss << ": " << ERROR_MSG;
+00086 #endif
+00087                 ss << ") " << std::endl;
+00088         }
+00089         _Reason = ss.str();
+00090   */
+00091         _Reason = "Socket error: ";
+00092         uint errornum = CSock::getLastError();
+00093         char str[256];
+00094         if ( addr != NULL )
+00095         {
+00096                 // Version with address
+00097                 smprintf( str, 256, reason, addr->asString().c_str() ); // reason *must* contain "%s"
+00098                 _Reason += str;
+00099         }
+00100         else
+00101         {
+00102                 // Version without address
+00103                 _Reason += reason;
+00104         }
+00105         if ( systemerror )
+00106         {
+00107                 _Reason += " (";
+00108                 smprintf( str, 256, "%d", errornum );
+00109                 _Reason += str;
+00110                 if ( errornum != 0 )
+00111                 {
+00112                         _Reason += ": ";
+00113                         _Reason += CSock::errorString( errornum );
+00114                 }
+00115                 _Reason += ")";
+00116         }
+00117         nlwarning( "Exception will be launched: %s", _Reason.c_str() );
+00118 }
+00119 
+00120 
+00121 /*
+00122  * Initializes the network engine if it is not already done (under Windows, calls WSAStartup()).
+00123  */
+00124 void CSock::initNetwork()
+00125 {
+00126         if ( ! CSock::_Initialized )
+00127         {
+00128 #ifdef NL_OS_WINDOWS
+00129                 WORD winsock_version = MAKEWORD( 2, 0 ); 
+00130                 WSADATA wsaData;
+00131                 if ( WSAStartup( winsock_version, &wsaData ) != 0 )
+00132                 {
+00133                         throw ESocket( "Winsock initialization failed" );
+00134                 }
+00135 #endif
+00136                 CSock::_Initialized = true;
+00137         }
+00138 }
+00139 
+00140 /*
+00141  * Releases the network engine
+00142  */
+00143 void CSock::releaseNetwork()
+00144 {
+00145 #ifdef NL_OS_WINDOWS
+00146         WSACleanup();
+00147 #endif
+00148         CSock::_Initialized = false;
+00149 }
+00150 
+00151 
+00152 /* Returns the code of the last error that has occured.
+00153  * Note: This code is platform-dependant. On Unix, it is errno; on Windows it is the Winsock error code.
+00154  * See also errorString()
+00155  */
+00156 uint CSock::getLastError()
+00157 {
+00158         return (uint)ERROR_NUM;
+00159 }
+00160 
+00161 
+00162 /*
+00163  * Returns a string explaining the network error (see getLastError())
+00164  */
+00165 std::string CSock::errorString( uint errorcode )
+00166 {
+00167 #ifdef NL_OS_WINDOWS
+00168         switch( errorcode )
+00169         {
+00170         case WSAEINTR            /*10004*/: return "Blocking operation interrupted";
+00171         case WSAEINVAL           /*10022*/: return "Invalid socket (maybe not bound) or argument";
+00172         case WSAEMFILE           /*10024*/: return "Too many open sockets";
+00173         case WSAENOTSOCK         /*10038*/: return "Socket operation on nonsocket (maybe invalid select descriptor)";
+00174         case WSAEMSGSIZE         /*10040*/: return "Message too long";
+00175         case WSAEADDRINUSE   /*10048*/: return "Address already in use (is this service already running in this computer?)";
+00176         case WSAEADDRNOTAVAIL/*10049*/: return "Address not available";
+00177         case WSAENETDOWN         /*10050*/: return "Network is down";
+00178         case WSAENETUNREACH  /*10051*/: return "Network is unreachable";
+00179         case WSAECONNRESET   /*10054*/: return "Connection reset by peer";
+00180         case WSAENOBUFS          /*10055*/: return "No buffer space available; please close applications or reboot";
+00181         case WSAESHUTDOWN        /*10058*/: return "Cannot send/receive after socket shutdown";
+00182         case WSAETIMEDOUT        /*10060*/: return "Connection timed-out";
+00183         case WSAECONNREFUSED /*10061*/: return "Connection refused, the server may be offline";
+00184         case WSAEHOSTUNREACH /*10065*/: return "Remote host is unreachable";
+00185         case WSANOTINITIALISED /*093*/: return "'Windows Sockets' not initialized";
+00186         default:                                                return "";
+00187         }
+00188 #elif defined NL_OS_UNIX
+00189         return std::string( strerror( errorcode ) );
+00190 #endif
+00191 
+00192 }
+00193 
+00194 
+00195 
+00196 /*
+00197  * Constructor
+00198  */
+00199 CSock::CSock( bool logging ) :
+00200         _Sock( INVALID_SOCKET ),
+00201         _Logging( logging ),
+00202         _BytesReceived( 0 ),
+00203         _BytesSent( 0 ),
+00204         _NonBlocking( false ),
+00205         _MaxReceiveTime( 0 ),
+00206         _MaxSendTime( 0 )
+00207 {
+00208         nlassert( CSock::_Initialized );
+00209         /*{
+00210                 CSynchronized<bool>::CAccessor sync( &_SyncConnected );
+00211                 sync.value() = false;
+00212         }*/
+00213         _Connected = false;
+00214 }
+00215 
+00216 
+00217 /*
+00218  * Construct a CSock object using an existing connected socket descriptor and its associated remote address
+00219  */
+00220 CSock::CSock( SOCKET sock, const CInetAddress& remoteaddr ) :
+00221         _Sock( sock ),
+00222         _Logging( true ),
+00223         _BytesReceived( 0 ),
+00224         _BytesSent( 0 ),
+00225         _RemoteAddr( remoteaddr ),
+00226         _NonBlocking( false ),
+00227         _MaxReceiveTime( 0 ),
+00228         _MaxSendTime( 0 )
+00229 {
+00230         nlassert( CSock::_Initialized );
+00231         /*{
+00232                 CSynchronized<bool>::CAccessor sync( &_SyncConnected );
+00233                 sync.value() = true;
+00234         }*/
+00235         _Connected = true;
+00236 
+00237         // Check remote address
+00238         if ( ! _RemoteAddr.isValid() )
+00239         {
+00240                 throw ESocket( "Could not init a socket object with an invalid address", false );
+00241         }
+00242 
+00243         // Get local socket name
+00244         setLocalAddress();
+00245 }
+00246 
+00247 
+00248 /*
+00249  * Creates the socket and get a valid descriptor
+00250  */
+00251 void CSock::createSocket( int type, int protocol )
+00252 {
+00253         nlassert( _Sock == INVALID_SOCKET );
+00254 
+00255         _Sock = socket( AF_INET, type, protocol ); // or IPPROTO_IP (=0) ?
+00256         if ( _Sock == INVALID_SOCKET )
+00257         {
+00258                 throw ESocket( "Socket creation failed" );
+00259         }
+00260 
+00261         if ( _Logging )
+00262         {
+00263 //              nldebug( "LNETL0: Socket %d open (TCP)", _Sock );
+00264         }
+00265 }
+00266 
+00267 
+00268 /*
+00269  * Closes the listening socket
+00270  */
+00271 void CSock::close()
+00272 {
+00273         if ( _Logging )
+00274         {
+00275                 nldebug( "LNETL0: Socket %d closing for %s at %s", _Sock, _RemoteAddr.asString().c_str(), _LocalAddr.asString().c_str() );
+00276         }
+00277 #ifdef NL_OS_WINDOWS
+00278         closesocket( _Sock );
+00279 #elif defined NL_OS_UNIX
+00280         ::close( _Sock );
+00281 #endif
+00282         _Sock = INVALID_SOCKET;
+00283 }
+00284 
+00285 
+00286 /*
+00287  * Destructor
+00288  */
+00289 CSock::~CSock()
+00290 {
+00291         nlinfo( "Report for %s socket %s: Max send time: %u Max recv time: %u", _NonBlocking?"non-blocking":"blocking", remoteAddr().asString().c_str(), _MaxSendTime, _MaxReceiveTime );
+00292         nlinfo( "Max send time: %u", _MaxSendTime);
+00293         if ( _Sock != INVALID_SOCKET )
+00294         {
+00295                 if ( _Logging )
+00296                 {
+00297                         nldebug( "LNETL0: Socket %d closing for %s at %s", _Sock, _RemoteAddr.asString().c_str(), _LocalAddr.asString().c_str() );
+00298                 }
+00299 
+00300                 if ( connected() )
+00301                 {
+00302 #ifdef NL_OS_WINDOWS
+00303                         shutdown( _Sock, SD_BOTH );
+00304                 }
+00305                 closesocket( _Sock );
+00306 #elif defined NL_OS_UNIX
+00307                         shutdown( _Sock, SHUT_RDWR );
+00308                 }
+00309                 ::close( _Sock );
+00310 #endif
+00311                 _Sock = INVALID_SOCKET;
+00312         }
+00313 }
+00314 
+00315 
+00316 /*
+00317  * Connection
+00318  */
+00319 void CSock::connect( const CInetAddress& addr )
+00320 {
+00321         nldebug( "LNETL0: Socket %d connecting to %s...", _Sock, addr.asString().c_str() );
+00322 
+00323         // Check address
+00324         if ( ! addr.isValid() )
+00325         {
+00326                 throw ESocket( "Unable to connect to invalid address", false );
+00327         }
+00328 
+00329 #ifndef NL_OS_WINDOWS
+00330         // Set Reuse Address On (does not work on Win98 and is useless on Win2000)
+00331         int value = true;
+00332         if ( setsockopt( _Sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value) ) == SOCKET_ERROR )
+00333         {
+00334                 throw ESocket( "ReuseAddr failed" );
+00335         }
+00336 #endif
+00337 
+00338         // Connection (when _Sock is a datagram socket, connect establishes a default destination address)
+00339         if ( ::connect( _Sock, (const sockaddr *)(addr.sockAddr()), sizeof(sockaddr_in) ) != 0 )
+00340         {
+00341 /*              if ( _Logging )
+00342                 {
+00343 #ifdef NL_OS_WINDOWS
+00344                         nldebug( "Impossible to connect socket %d to %s %s (%d)", _Sock, addr.hostName().c_str(), addr.asIPString().c_str(), ERROR_NUM );
+00345 #elif defined NL_OS_UNIX
+00346                         nldebug( "Impossible to connect socket %d to %s %s (%d:%s)", _Sock, addr.hostName().c_str(), addr.asIPString().c_str(), ERROR_NUM, strerror(ERROR_NUM) );
+00347 #endif
+00348                 }
+00349 */
+00350                 throw ESocketConnectionFailed( addr );
+00351         }
+00352         setLocalAddress();
+00353         if ( _Logging )
+00354         {
+00355                 nldebug( "LNETL0: Socket %d connected to %s (local %s)", _Sock, addr.asString().c_str(), _LocalAddr.asString().c_str() );
+00356         }       
+00357         _RemoteAddr = addr;
+00358 
+00359         _BytesReceived = 0;
+00360         _BytesSent = 0;
+00361 
+00362         /*CSynchronized<bool>::CAccessor sync( &_SyncConnected );
+00363         sync.value() = true;*/
+00364         _Connected = true;
+00365 }
+00366 
+00367 
+00368 /*
+00369  * Checks if there is some data to receive
+00370  */
+00371 bool CSock::dataAvailable()
+00372 {
+00373         fd_set fdset;
+00374         FD_ZERO( &fdset );
+00375         FD_SET( _Sock, &fdset );
+00376         timeval tv;
+00377         tv.tv_sec = CSock::_TimeoutS;
+00378         tv.tv_usec = CSock::_TimeoutMs;
+00379 
+00380         // Test for message received.
+00381         int res = select( _Sock+1, &fdset, NULL, NULL, &tv );
+00382         switch ( res  )
+00383         {
+00384                 case  0 : return false;
+00385                 case -1 : throw ESocket( "CSock::dataAvailable(): select failed" ); return false;
+00386                 default : return true;
+00387         }
+00388 }
+00389 
+00390 
+00391 /*
+00392  * Sets the local address
+00393  */
+00394 void CSock::setLocalAddress()
+00395 {
+00396         sockaddr saddr;
+00397         socklen_t saddrlen = sizeof(saddr);
+00398         if ( getsockname( _Sock, &saddr, &saddrlen ) != 0 )
+00399         {
+00400                 throw ESocket( "Unable to find local address" );
+00401         }
+00402         _LocalAddr.setSockAddr( (const sockaddr_in *)&saddr );
+00403 }
+00404 
+00405 
+00406 /*
+00407  * Sends data, or returns false if it would block
+00408  */
+00409 CSock::TSockResult CSock::send( const uint8 *buffer, uint32& len, bool throw_exception )
+00410 {
+00411         uint32 realLen = len;
+00412         TTicks before = CTime::getPerformanceTime();
+00413         len = ::send( _Sock, (const char*)buffer, len, 0 );
+00414         _MaxSendTime = max( (uint32)(CTime::ticksToSecond(CTime::getPerformanceTime()-before)*1000.0f), _MaxSendTime );
+00415 
+00416         if ( _Logging )
+00417         {
+00418 //              nldebug ("LNETL0: CSock::send(): Sent %d bytes to %d res: %d (%d)", realLen, _Sock, len, ERROR_NUM);
+00419         }
+00420         
+00421         if ( len == SOCKET_ERROR )
+00422         {
+00423                 if ( ERROR_NUM == ERROR_WOULDBLOCK )
+00424                 {
+00425                         len = 0;
+00426                         return Ok;
+00427                 }
+00428                 if ( throw_exception )
+00429                 {
+00430                         throw ESocket( "Unable to send data" );
+00431                 }
+00432                 return Error;
+00433         }
+00434         _BytesSent += len;
+00435         
+00436         return Ok;
+00437 }
+00438 
+00439 
+00440 
+00441 /*
+00442  * Receives data
+00443  */
+00444 CSock::TSockResult CSock::receive( uint8 *buffer, uint32& len, bool throw_exception )
+00445 {
+00446         if ( _NonBlocking )
+00447         {
+00448                 // Receive incoming message (only the received part)
+00449 
+00450                 uint32 realLen = len;
+00451 
+00452                 TTicks before = CTime::getPerformanceTime();
+00453                 len = ::recv( _Sock, (char*)buffer, len, 0 );
+00454 
+00455                 if ( _Logging )
+00456                 {
+00457 //                      nldebug ("LNETL0: CSock::receive(): NBM Received %d bytes to %d res: %d (%d)", realLen, _Sock, len, ERROR_NUM);
+00458                 }
+00459 
+00460                 _MaxReceiveTime = max( (uint32)(CTime::ticksToSecond(CTime::getPerformanceTime()-before)*1000.0f), _MaxReceiveTime );
+00461                 switch ( len )
+00462                 {
+00463                         // Graceful disconnection
+00464                         case 0 :
+00465                         {
+00466                                 /*{
+00467                                         CSynchronized<bool>::CAccessor sync( &_SyncConnected );
+00468                                         sync.value() = false;
+00469                                 }*/
+00470                                 _Connected = false;
+00471                                 if ( throw_exception )
+00472                                 {
+00473                                         throw ESocketConnectionClosed();
+00474                                 }
+00475                                 return CSock::ConnectionClosed;
+00476                         }
+00477 
+00478                         // Socket error or call would block
+00479                         case SOCKET_ERROR :
+00480                         {
+00481                                 len = 0;
+00482                                 if ( ERROR_NUM == ERROR_WOULDBLOCK )
+00483                                 {
+00484                                         // Call would block
+00485                                         return CSock::WouldBlock;
+00486                                 }
+00487                                 else
+00488                                 {
+00489                                         // Socket error
+00490                                         if ( throw_exception )
+00491                                         {
+00492                                                 throw ESocket( "Unable to receive data" );
+00493                                         }
+00494                                         return CSock::Error;
+00495                                 }
+00496                         }
+00497                 }
+00498         }
+00499         else // Blocking Mode
+00500         {
+00501                 // Receive incoming message, waiting until a complete message has arrived
+00502                 uint total = 0;
+00503                 uint brecvd;
+00504                 
+00505                 uint32 realLen = len;
+00506                 
+00507                 while ( total < len )
+00508                 {
+00509                         TTicks before = CTime::getPerformanceTime();
+00510                         brecvd = ::recv( _Sock, (char*)(buffer+total), len-total, 0 );
+00511 
+00512 //                      nldebug ("LNETL0: CSock::receive(): BM Received %d bytes to %d res: %d (%d)", realLen, _Sock, len, ERROR_NUM);
+00513 
+00514                         _MaxReceiveTime = max( (uint32)(CTime::ticksToSecond(CTime::getPerformanceTime()-before)*1000.0f), _MaxReceiveTime );
+00515                         
+00516                         switch ( brecvd )
+00517                         {
+00518                                 // Graceful disconnection
+00519                                 case 0 : 
+00520                                 {
+00521                                         /*{
+00522                                                 CSynchronized<bool>::CAccessor sync( &_SyncConnected );
+00523                                                 sync.value() = false;
+00524                                         }*/
+00525                                         _Connected = false;
+00526                                         if ( throw_exception )
+00527                                         {
+00528                                                 throw ESocketConnectionClosed();
+00529                                         }
+00530                                         return CSock::ConnectionClosed;
+00531                                 }
+00532 
+00533                                 // Socket error
+00534                                 case SOCKET_ERROR :
+00535                                 {
+00536                                         if ( throw_exception )
+00537                                         {
+00538                                                 throw ESocket( "Unable to receive data" );
+00539                                         }
+00540                                         return CSock::Error;
+00541                                 }
+00542                         }
+00543                         total += brecvd;
+00544                 }
+00545         }
+00546 
+00547         /*if ( _Logging )
+00548         {
+00549                 nldebug( "LNETL0: Socket %d received %d bytes", _Sock, len );
+00550         }*/
+00551         _BytesReceived += len;
+00552         return CSock::Ok;
+00553 }
+00554 
+00555 
+00556 /*
+00557  * Returns if the socket is connected
+00558  */
+00559 bool CSock::connected()
+00560 {
+00561   /*bool b;
+00562   {
+00563     //nldebug( "LNETL0: CSock::connected-BEGIN (socket %u)", descriptor() );
+00564     CSynchronized<bool>::CAccessor sync( &_SyncConnected );
+00565     b = sync.value();
+00566   }
+00567   //nldebug( "LNETL0: CSock::connected-END" );
+00568   return b;*/
+00569         return _Connected;
+00570 }
+00571 
+00572 
+00573 /*
+00574  * Sets the socket in nonblocking mode
+00575  */
+00576 void CSock::setNonBlockingMode ( bool bm )
+00577 {
+00578         if ( _NonBlocking != bm )
+00579         {
+00580 #ifdef NL_OS_WINDOWS
+00581                 u_long b = bm;
+00582                 if ( ioctlsocket( _Sock, FIONBIO, &b ) != 0 )
+00583 #else
+00584                 if ( fcntl( _Sock, F_SETFL, FNDELAY | fcntl( _Sock, F_GETFL, 0 ) ) == -1 )
+00585 #endif
+00586                 {
+00587                         throw ESocket( "Cannot set nonblocking mode" );
+00588                 }
+00589                 _NonBlocking = bm;
+00590         }
+00591 }
+00592 
+00593 
+00594 } // NLNET
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1