# 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  

listen_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/listen_sock.h"
00029 
00030 #ifdef NL_OS_WINDOWS
00031 
00032 #include <winsock2.h>
00033 typedef sint socklen_t;
00034 
00035 #elif defined NL_OS_UNIX
00036 
00037 #include <unistd.h>
00038 #include <sys/types.h>
00039 #include <sys/socket.h>
00040 #include <netinet/in.h>
00041 #include <arpa/inet.h>
00042 #include <netdb.h>
00043 #include <errno.h>
00044 #include <fcntl.h>
00045 #define SOCKET_ERROR -1
00046 #define INVALID_SOCKET -1
00047 typedef int SOCKET;
00048 
00049 #endif
00050 
00051 
00052 using namespace std;
00053 
00054 
00055 namespace NLNET
00056 {
00057 
00058 
00059 /*
00060  * Constructor
00061  */
00062 CListenSock::CListenSock() : CTcpSock(), _Bound( false )
00063 {
00064         // Create socket
00065         createSocket( SOCK_STREAM, IPPROTO_TCP );
00066 
00068         setBacklog( -1 );
00069 }
00070 
00071 
00072 /*
00073  * Prepares to receive connections on a specified port
00074  */
00075 void CListenSock::init( uint16 port )
00076 {
00077     // Use any address
00078         CInetAddress localaddr; // By default, INETADDR_ANY (useful for gateways that have several ip addresses)
00079         localaddr.setPort( port );
00080         init( localaddr );
00081 
00082         // Now set the address visible from outside
00083         _LocalAddr = CInetAddress::localHost();
00084         _LocalAddr.setPort( port );
00085         nldebug( "LNETL0: Socket %d listen socket is at %s", _Sock, _LocalAddr.asString().c_str() );
00086 }
00087 
00088 
00089 /*
00090  * Prepares to receive connections on a specified address/port (useful when the host has several addresses)
00091  */
00092 void CListenSock::init( const CInetAddress& addr )
00093 {
00094         if ( ! addr.isValid() )
00095         {
00096                 nldebug( "LNETL0: Binding listen socket to any address, port %hu", addr.port() );
00097         }
00098 
00099 #ifndef NL_OS_WINDOWS
00100         // Set Reuse Address On (does not work on Win98 and is useless on Win2000)
00101         int value = true;
00102         if ( setsockopt( _Sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value) ) == SOCKET_ERROR )
00103         {
00104                 throw ESocket( "ReuseAddr failed" );
00105         }
00106 #endif
00107 
00108         // Bind socket to port  
00109         if ( ::bind( _Sock, (const sockaddr *)addr.sockAddr(), sizeof(sockaddr_in) ) != 0 )
00110         {
00111                 throw ESocket( "Unable to bind listen socket to port" );
00112         }
00113         _LocalAddr = addr;
00114         _Bound = true;
00115 
00116         // Listen
00117         if ( ::listen( _Sock, _BackLog ) != 0 ) // SOMAXCONN = maximum length of the queue of pending connections
00118         {
00119                 throw ESocket( "Unable to listen on specified port" );
00120         }
00121 //      nldebug( "LNETL0: Socket %d listening at %s", _Sock, _LocalAddr.asString().c_str() );
00122 }
00123 
00124 
00125 /*
00126  * Accepts an incoming connection, and creates a new socket
00127  */
00128 CTcpSock *CListenSock::accept()
00129 {
00130         // Accept connection
00131         sockaddr_in saddr;
00132         socklen_t saddrlen = sizeof(saddr);
00133         SOCKET newsock = ::accept( _Sock, (sockaddr*)&saddr, &saddrlen );
00134         if ( newsock == INVALID_SOCKET )
00135         {
00136           /*nlinfo( "LNETL0: Error accepting a connection");
00137           // See accept() man on Linux
00138           newsock = ::accept( _Sock, (sockaddr*)&saddr, &saddrlen );
00139           if ( newsock == INVALID_SOCKET )*/
00140             {
00141                         throw ESocket( "Accept returned an invalid socket");
00142             }
00143         }
00144 
00145         // Construct and save a CTcpSock object
00146         CInetAddress addr;
00147         addr.setSockAddr( &saddr );
00148         nldebug( "LNETL0: Socket %d accepted an incoming connection from %s, opening socket %d", _Sock, addr.asString().c_str(), newsock );
00149         CTcpSock *connection = new CTcpSock( newsock, addr );
00150         return connection;
00151 }
00152 
00153 
00154 /*
00155  * Sets the number of the pending connections queue. -1 for the maximum possible value.
00156  */
00157 void CListenSock::setBacklog( sint backlog )
00158 {
00159         if ( backlog == -1 )
00160         {
00161                 _BackLog = SOMAXCONN; // SOMAXCONN = maximum length of the queue of pending connections
00162         }
00163         else
00164         {
00165                 _BackLog = backlog;
00166         }
00167         if ( _Bound )
00168         {
00169                 if ( ::listen( _Sock, _BackLog ) != 0 )
00170                 {
00171                         throw ESocket( "Unable to listen on specified port, while changing backlog" );
00172                 }
00173         }
00174 }
00175 
00176 
00177 } // NLNET