# 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  

tcp_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/tcp_sock.h"
00029 
00030 #ifdef NL_OS_WINDOWS
00031 #include <winsock2.h>
00032 #define socklen_t int
00033 #define ERROR_NUM WSAGetLastError()
00034 
00035 #elif defined NL_OS_UNIX
00036 #include <unistd.h>
00037 #include <sys/types.h>
00038 #include <sys/time.h>
00039 #include <sys/socket.h>
00040 #include <netinet/in.h>
00041 #include <netinet/tcp.h>
00042 #include <arpa/inet.h>
00043 #include <netdb.h>
00044 #include <errno.h>
00045 #define SOCKET_ERROR -1
00046 #define INVALID_SOCKET -1
00047 #define ERROR_NUM errno
00048 #define ERROR_MSG strerror(errno)
00049 typedef int SOCKET;
00050 
00051 #endif
00052 
00053 using namespace NLMISC;
00054 
00055 namespace NLNET {
00056 
00057 
00058 /*
00059  * Constructor
00060  */
00061 CTcpSock::CTcpSock( bool logging ) :
00062         CSock( logging )
00063 {}
00064 
00065 
00066 /*
00067  * Construct a CTcpSocket object using an already connected socket 
00068  */
00069 CTcpSock::CTcpSock( SOCKET sock, const CInetAddress& remoteaddr ) :
00070         CSock( sock, remoteaddr )
00071 {}
00072 
00073 
00074 /* Connection. You can reconnect a socket after being disconnected.
00075  * This method does not return a boolean, otherwise a programmer could ignore the result and no
00076  * exception would be thrown if connection fails :
00077  * - If addr is not valid, an exception ESocket is thrown
00078  * - If connect() fails for another reason, an exception ESocketConnectionFailed is thrown
00079  */
00080 void CTcpSock::connect( const CInetAddress& addr )
00081 {
00082         // Create a new socket
00083         if ( _Sock != INVALID_SOCKET )
00084         {
00085           if ( _Logging )
00086             {
00087 //              nldebug( "LNETL0: Closing socket %d before reconnecting", _Sock );
00088             }
00089           close();
00090         }       
00091         createSocket( SOCK_STREAM, IPPROTO_TCP );
00092 
00093         // Connection
00094         CSock::connect( addr );
00095 }
00096 
00097 
00098 /*
00099  * Active disconnection. After disconnecting, you can't connect back with the same socket.
00100  */
00101 void CTcpSock::disconnect()
00102 {
00103         nldebug( "LNETL0: Socket %d disconnecting from %s...", _Sock, _RemoteAddr.asString().c_str() );
00104 
00105         // This shutdown resets the connection immediatly (not a graceful closure)
00106 #ifdef NL_OS_WINDOWS
00107         ::shutdown( _Sock, SD_BOTH );
00108 #elif defined NL_OS_UNIX
00109         ::shutdown( _Sock, SHUT_RDWR );
00110 #endif
00111         /*CSynchronized<bool>::CAccessor sync( &_SyncConnected );
00112         sync.value() = false;*/
00113         _Connected = false;
00114 }
00115 
00116 
00117 /*
00118  * Active disconnection for download way only
00119  */
00120 void CTcpSock::shutdownReceiving()
00121 {
00122 #ifdef NL_OS_WINDOWS
00123         ::shutdown( _Sock, SD_RECEIVE );
00124 #elif defined NL_OS_UNIX
00125         ::shutdown( _Sock, SHUT_RD );
00126 #endif
00127 }
00128 
00129 
00130 /*
00131  * Active disconnection for upload way only
00132  */
00133 void CTcpSock::shutdownSending()
00134 {
00135 #ifdef NL_OS_WINDOWS
00136         ::shutdown( _Sock, SD_SEND );
00137 #elif defined NL_OS_UNIX
00138         ::shutdown( _Sock, SHUT_WR );
00139 #endif
00140 }
00141 
00142 
00143 /*
00144  * Sets/unsets TCP_NODELAY
00145  */
00146 void CTcpSock::setNoDelay( bool value )
00147 {
00148         int b = value?1:0;
00149         if ( setsockopt( _Sock, IPPROTO_TCP, TCP_NODELAY, (char*)&b, sizeof(b) ) != 0 )
00150         {
00151                 throw ESocket( "setNoDelay failed" );
00152         }
00153 }
00154 
00155 
00156 /* Sets a custom TCP Window size (SO_RCVBUF and SO_SNDBUF).
00157  * You must close the socket is necessary, before calling this method.
00158  *
00159  * See http://www.ncsa.uiuc.edu/People/vwelch/net_perf/tcp_windows.html
00160  */
00161 void CTcpSock::connectWithCustomWindowSize( const CInetAddress& addr, int windowsize )
00162 {
00163         // Create socket
00164         if ( _Sock != INVALID_SOCKET )
00165         {
00166                 nlerror( "Cannot connect with custom window size when already connected" );
00167         }
00168         createSocket( SOCK_STREAM, IPPROTO_TCP );
00169 
00170         // Change window size
00171         if ( setsockopt( _Sock, SOL_SOCKET, SO_SNDBUF, (char*)&windowsize, sizeof(windowsize) ) != 0
00172           || setsockopt( _Sock, SOL_SOCKET, SO_RCVBUF, (char*)&windowsize, sizeof(windowsize) ) != 0 )
00173         {
00174                 throw ESocket( "setWindowSize failed" );
00175         }
00176         
00177         // Connection
00178         CSock::connect( addr );
00179 }
00180 
00181 
00182 /*
00183  * Returns the TCP Window Size for the current socket
00184  */
00185 uint32 CTcpSock::getWindowSize()
00186 {
00187         int windowsize = 0;
00188         socklen_t len = sizeof( windowsize );
00189 
00190         /* send buffer -- query for buffer size */
00191         if ( getsockopt( _Sock, SOL_SOCKET, SO_SNDBUF, (char*) &windowsize, &len ) == 0 )
00192         {
00193                 return windowsize;
00194         }
00195         else
00196         {
00197                 return 0;
00198         }
00199 }
00200 
00201 
00202 } // NLNET