src/qt3support/network/q3serversocket.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt3Support module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "q3serversocket.h"
       
    43 
       
    44 #ifndef QT_NO_NETWORK
       
    45 
       
    46 #include "qsocketnotifier.h"
       
    47 
       
    48 QT_BEGIN_NAMESPACE
       
    49 
       
    50 class Q3ServerSocketPrivate {
       
    51 public:
       
    52     Q3ServerSocketPrivate(): s(0), n(0) {}
       
    53     ~Q3ServerSocketPrivate() { delete n; delete s; }
       
    54     Q3SocketDevice *s;
       
    55     QSocketNotifier *n;
       
    56 };
       
    57 
       
    58 
       
    59 /*!
       
    60     \class Q3ServerSocket
       
    61     \brief The Q3ServerSocket class provides a TCP-based server.
       
    62 
       
    63     \compat
       
    64 
       
    65     This class is a convenience class for accepting incoming TCP
       
    66     connections. You can specify the port or have Q3ServerSocket pick
       
    67     one, and listen on just one address or on all the machine's
       
    68     addresses.
       
    69 
       
    70     Using the API is very simple: subclass Q3ServerSocket, call the
       
    71     constructor of your choice, and implement newConnection() to
       
    72     handle new incoming connections. There is nothing more to do.
       
    73 
       
    74     (Note that due to lack of support in the underlying APIs,
       
    75     Q3ServerSocket cannot accept or reject connections conditionally.)
       
    76 
       
    77     \sa Q3Socket, Q3SocketDevice, QHostAddress, QSocketNotifier
       
    78 */
       
    79 
       
    80 
       
    81 /*!
       
    82     Creates a server socket object, that will serve the given \a port
       
    83     on all the addresses of this host. If \a port is 0, Q3ServerSocket
       
    84     will pick a suitable port in a system-dependent manner. Use \a
       
    85     backlog to specify how many pending connections the server can
       
    86     have.
       
    87 
       
    88     The \a parent and \a name arguments are passed on to the QObject
       
    89     constructor.
       
    90 
       
    91     \warning On Tru64 Unix systems a value of 0 for \a backlog means
       
    92     that you don't accept any connections at all; you should specify a
       
    93     value larger than 0.
       
    94 */
       
    95 
       
    96 Q3ServerSocket::Q3ServerSocket( Q_UINT16 port, int backlog,
       
    97 			      QObject *parent, const char *name )
       
    98     : QObject( parent, name )
       
    99 {
       
   100     d = new Q3ServerSocketPrivate;
       
   101     init( QHostAddress(), port, backlog );
       
   102 }
       
   103 
       
   104 
       
   105 /*!
       
   106     Creates a server socket object, that will serve the given \a port
       
   107     only on the given \a address. Use \a backlog to specify how many
       
   108     pending connections the server can have.
       
   109 
       
   110     The \a parent and \a name arguments are passed on to the QObject
       
   111     constructor.
       
   112 
       
   113     \warning On Tru64 Unix systems a value of 0 for \a backlog means
       
   114     that you don't accept any connections at all; you should specify a
       
   115     value larger than 0.
       
   116 */
       
   117 
       
   118 Q3ServerSocket::Q3ServerSocket( const QHostAddress & address, Q_UINT16 port,
       
   119 			      int backlog,
       
   120 			      QObject *parent, const char *name )
       
   121     : QObject( parent, name )
       
   122 {
       
   123     d = new Q3ServerSocketPrivate;
       
   124     init( address, port, backlog );
       
   125 }
       
   126 
       
   127 
       
   128 /*!
       
   129     Construct an empty server socket.
       
   130 
       
   131     This constructor, in combination with setSocket(), allows us to
       
   132     use the Q3ServerSocket class as a wrapper for other socket types
       
   133     (e.g. Unix Domain Sockets under Unix).
       
   134 
       
   135     The \a parent and \a name arguments are passed on to the QObject
       
   136     constructor.
       
   137 
       
   138     \sa setSocket()
       
   139 */
       
   140 
       
   141 Q3ServerSocket::Q3ServerSocket( QObject *parent, const char *name )
       
   142     : QObject( parent, name )
       
   143 {
       
   144     d = new Q3ServerSocketPrivate;
       
   145 }
       
   146 
       
   147 
       
   148 /*!
       
   149     Returns true if the construction succeeded; otherwise returns false.
       
   150 */
       
   151 bool Q3ServerSocket::ok() const
       
   152 {
       
   153     return !!d->s;
       
   154 }
       
   155 
       
   156 /*
       
   157   The common bit of the constructors.
       
   158  */
       
   159 void Q3ServerSocket::init( const QHostAddress & address, Q_UINT16 port, int backlog )
       
   160 {
       
   161     d->s = new Q3SocketDevice( Q3SocketDevice::Stream, address.isIPv4Address()
       
   162 			      ? Q3SocketDevice::IPv4 : Q3SocketDevice::IPv6, 0 );
       
   163 #if !defined(Q_OS_WIN32)
       
   164     // Under Unix, we want to be able to use the port, even if a socket on the
       
   165     // same address-port is in TIME_WAIT. Under Windows this is possible anyway
       
   166     // -- furthermore, the meaning of reusable is different: it means that you
       
   167     // can use the same address-port for multiple listening sockets.
       
   168     d->s->setAddressReusable( true );
       
   169 #endif
       
   170     if ( d->s->bind( address, port )
       
   171       && d->s->listen( backlog ) )
       
   172     {
       
   173 	d->n = new QSocketNotifier( d->s->socket(), QSocketNotifier::Read,
       
   174 				    this, "accepting new connections" );
       
   175 	connect( d->n, SIGNAL(activated(int)),
       
   176 		 this, SLOT(incomingConnection(int)) );
       
   177     } else {
       
   178 	qWarning( "Q3ServerSocket: failed to bind or listen to the socket" );
       
   179 	delete d->s;
       
   180 	d->s = 0;
       
   181     }
       
   182 }
       
   183 
       
   184 
       
   185 /*!
       
   186     Destroys the socket.
       
   187 
       
   188     This causes any backlogged connections (connections that have
       
   189     reached the host, but not yet been completely set up by calling
       
   190     Q3SocketDevice::accept()) to be severed.
       
   191 
       
   192     Existing connections continue to exist; this only affects the
       
   193     acceptance of new connections.
       
   194 */
       
   195 Q3ServerSocket::~Q3ServerSocket()
       
   196 {
       
   197     delete d;
       
   198 }
       
   199 
       
   200 
       
   201 /*!
       
   202     \fn void Q3ServerSocket::newConnection( int socket )
       
   203 
       
   204     This pure virtual function is responsible for setting up a new
       
   205     incoming connection. \a socket is the fd (file descriptor) for the
       
   206     newly accepted connection.
       
   207 */
       
   208 
       
   209 
       
   210 void Q3ServerSocket::incomingConnection( int )
       
   211 {
       
   212     int fd = d->s->accept();
       
   213     if ( fd >= 0 )
       
   214 	newConnection( fd );
       
   215 }
       
   216 
       
   217 
       
   218 /*!
       
   219     Returns the port number on which this server socket listens. This
       
   220     is always non-zero; if you specify 0 in the constructor,
       
   221     Q3ServerSocket will pick a non-zero port itself. ok() must be true
       
   222     before calling this function.
       
   223 
       
   224     \sa address() Q3SocketDevice::port()
       
   225 */
       
   226 Q_UINT16 Q3ServerSocket::port() const
       
   227 {
       
   228     if ( !d || !d->s )
       
   229 	return 0;
       
   230     return d->s->port();
       
   231 }
       
   232 
       
   233 
       
   234 /*!
       
   235     Returns the operating system socket.
       
   236 */
       
   237 int Q3ServerSocket::socket() const
       
   238 {
       
   239     if ( !d || !d->s )
       
   240 	return -1;
       
   241 
       
   242     return d->s->socket();
       
   243 }
       
   244 
       
   245 /*!
       
   246     Returns the address on which this object listens, or 0.0.0.0 if
       
   247     this object listens on more than one address. ok() must be true
       
   248     before calling this function.
       
   249 
       
   250     \sa port() Q3SocketDevice::address()
       
   251 */
       
   252 QHostAddress Q3ServerSocket::address() const
       
   253 {
       
   254     if ( !d || !d->s )
       
   255 	return QHostAddress();
       
   256 
       
   257     return d->s->address();
       
   258 }
       
   259 
       
   260 
       
   261 /*!
       
   262     Returns a pointer to the internal socket device. The returned
       
   263     pointer is 0 if there is no connection or pending connection.
       
   264 
       
   265     There is normally no need to manipulate the socket device directly
       
   266     since this class does all the necessary setup for most client or
       
   267     server socket applications.
       
   268 */
       
   269 Q3SocketDevice *Q3ServerSocket::socketDevice()
       
   270 {
       
   271     if ( !d )
       
   272 	return 0;
       
   273 
       
   274     return d->s;
       
   275 }
       
   276 
       
   277 
       
   278 /*!
       
   279     Sets the socket to use \a socket. bind() and listen() should
       
   280     already have been called for \a socket.
       
   281 
       
   282     This allows us to use the Q3ServerSocket class as a wrapper for
       
   283     other socket types (e.g. Unix Domain Sockets).
       
   284 */
       
   285 void Q3ServerSocket::setSocket( int socket )
       
   286 {
       
   287     delete d;
       
   288     d = new Q3ServerSocketPrivate;
       
   289     d->s = new Q3SocketDevice( socket, Q3SocketDevice::Stream );
       
   290     d->n = new QSocketNotifier( d->s->socket(), QSocketNotifier::Read,
       
   291 	       this, "accepting new connections" );
       
   292     connect( d->n, SIGNAL(activated(int)),
       
   293 	     this, SLOT(incomingConnection(int)) );
       
   294 }
       
   295 
       
   296 QT_END_NAMESPACE
       
   297 
       
   298 #endif //QT_NO_NETWORK