1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
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
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.
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.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qunixsocketserver_p.h"
44 // #define QUNIXSOCKETSERVER_DEBUG
46 #ifdef QUNIXSOCKETSERVER_DEBUG
50 #include <QtCore/qsocketnotifier.h>
53 #include <sys/types.h>
54 #include <sys/socket.h>
60 #define UNIX_PATH_MAX 108 // From unix(7)
64 class QUnixSocketServerPrivate : public QObject
68 QUnixSocketServerPrivate(QUnixSocketServer * parent)
69 : QObject(), me(parent), fd(-1), maxConns(30),
70 error(QUnixSocketServer::NoError), acceptNotifier(0)
73 QUnixSocketServer * me;
77 QUnixSocketServer::ServerError error;
78 QSocketNotifier * acceptNotifier;
80 void acceptActivated();
84 \class QUnixSocketServer
87 \brief The QUnixSocketServer class provides a Unix domain socket based server.
89 \ingroup Platform::DeviceSpecific
91 \ingroup Platform::Communications
95 This class makes it possible to accept incoming Unix domain socket
96 connections. Call \l QUnixSocketServer::listen() to have the server listen
97 for incoming connections on a specified path. The pure virtual
98 \l QUnixSocketServer::incomingConnection() is called each time a new
99 connection is established. Users must inherit from QUnixSocketServer and
100 implement this method.
102 If an error occurs, \l QUnixSocketServer::serverError() returns the type of
103 error. Errors can only occur during server establishment - that is, during a
104 call to \l QUnixSocketServer::listen(). Calling \l QUnixSocketServer::close()
105 causes QUnixSocketServer to stop listening for connections and reset its
108 QUnixSocketServer is often used in conjunction with the \l QUnixSocket class.
114 \enum QUnixSocketServer::ServerError
116 The ServerError enumeration represents the errors that can occur during server
117 establishment. The most recent error can be retrieved through a call to
118 \l QUnixSocketServer::serverError().
120 \value NoError No error has occurred.
121 \value InvalidPath An invalid path endpoint was passed to
122 \l QUnixSocketServer::listen(). As defined by unix(7), invalid paths
123 include an empty path, or what more than 107 characters long.
124 \value ResourceError An error acquiring or manipulating the system's socket
125 resources occurred. For example, if the process runs out of available
126 socket descriptors, a ResourceError will occur.
127 \value BindError The server was unable to bind to the specified path.
128 \value ListenError The server was unable to listen on the specified path for
129 incoming connections.
133 Create a new Unix socket server with the given \a parent.
135 QUnixSocketServer::QUnixSocketServer(QObject *parent)
136 : QObject(parent), d(0)
141 Stops listening for incoming connection and destroys the Unix socket server.
143 QUnixSocketServer::~QUnixSocketServer()
151 Stop listening for incoming connections and resets the Unix socket server's
152 state. Calling this method while \l {QUnixSocketServer::isListening()}{not listening } for incoming connections is a no-op.
154 \sa QUnixSocketServer::listen()
156 void QUnixSocketServer::close()
161 if(d->acceptNotifier) {
162 d->acceptNotifier->setEnabled(false);
163 delete d->acceptNotifier;
165 d->acceptNotifier = 0;
168 #ifdef QUNIXSOCKET_DEBUG
172 #ifdef QUNIXSOCKET_DEBUG
174 qDebug() << "QUnixSocketServer: Unable to close socket ("
175 << strerror(errno) << ')';
180 d->address = QByteArray();
185 Returns the last server error. Errors may only occur within a call to
186 \l QUnixSocketServer::listen(), and only when such a call fails.
188 This method is not destructive, so multiple calls to
189 QUnixSocketServer::serverError() will return the same value. The error is
190 only reset by an explicit call to \l QUnixSocketServer::close() or
191 by further calls to \l QUnixSocketServer::listen().
193 QUnixSocketServer::ServerError QUnixSocketServer::serverError() const
202 Returns true if this server is listening for incoming connections, false
205 \sa QUnixSocketServer::listen()
207 bool QUnixSocketServer::isListening() const
212 return (-1 != d->fd);
216 Tells the server to listen for incoming connections on \a path. Returns true
217 if it successfully initializes, false otherwise. In the case of failure, the
218 \l QUnixSocketServer::serverError() error status is set accordingly.
220 Calling this method while the server is already running will result in the
221 server begin reset, and then attempting to listen on \a path. This will not
222 affect connections established prior to the server being reset, but further
223 incoming connections on the previous path will be refused.
225 The server can be explicitly reset by a call to \l QUnixSocketServer::close().
227 \sa QUnixSocketServer::close()
229 bool QUnixSocketServer::listen(const QByteArray & path)
232 close(); // Any existing server is destroyed
234 d = new QUnixSocketServerPrivate(this);
237 if(path.isEmpty() || path.size() > UNIX_PATH_MAX) {
238 d->error = InvalidPath;
241 unlink( path ); // ok if this fails
244 d->fd = ::socket(PF_UNIX, SOCK_STREAM, 0);
246 #ifdef QUNIXSOCKETSERVER_DEBUG
247 qDebug() << "QUnixSocketServer: Unable to create socket ("
248 << strerror(errno) << ')';
251 d->error = ResourceError;
255 // Construct our unix address
256 struct ::sockaddr_un addr;
257 addr.sun_family = AF_UNIX;
258 ::memcpy(addr.sun_path, path.data(), path.size());
259 if(path.size() < UNIX_PATH_MAX)
260 addr.sun_path[path.size()] = '\0';
263 if(-1 == ::bind(d->fd, (sockaddr *)&addr, sizeof(sockaddr_un))) {
264 #ifdef QUNIXSOCKETSERVER_DEBUG
265 qDebug() << "QUnixSocketServer: Unable to bind socket ("
266 << strerror(errno) << ')';
269 d->error = BindError;
274 if(-1 == ::listen(d->fd, d->maxConns)) {
275 #ifdef QUNIXSOCKETSERVER_DEBUG
276 qDebug() << "QUnixSocketServer: Unable to listen socket ("
277 << strerror(errno) << ')';
280 d->error = ListenError;
286 d->acceptNotifier = new QSocketNotifier(d->fd, QSocketNotifier::Read, d);
287 d->acceptNotifier->setEnabled(true);
288 QObject::connect(d->acceptNotifier, SIGNAL(activated(int)),
289 d, SLOT(acceptActivated()));
295 Returns the Unix path on which this server is listening. If this server is
296 not listening, and empty address will be returned.
298 QByteArray QUnixSocketServer::serverAddress() const
305 int QUnixSocketServer::socketDescriptor() const
314 Returns the maximum length the queue of pending connections may grow to. That
315 is, the maximum number of clients attempting to connect for which the Unix
316 socket server has not yet accepted and passed to
317 \l QUnixSocketServer::incomingConnection(). If a connection request arrives
318 with the queue full, the client may receive a connection refused notification.
320 By default a queue length of 30 is used.
322 \sa QUnixSocketServer::setMaxPendingConnections()
324 int QUnixSocketServer::maxPendingConnections() const
333 Sets the maximum length the queue of pending connections may grow to
334 \a numConnections. This value will only apply to
335 \l QUnixSocketServer::listen() calls made following the value change - it will
336 not be retroactively applied.
338 \sa QUnixSocketServer::maxPendingConnections()
340 void QUnixSocketServer::setMaxPendingConnections(int numConnections)
342 Q_ASSERT(numConnections >= 1);
344 d = new QUnixSocketServerPrivate(this);
346 d->maxConns = numConnections;
350 \fn void QUnixSocketServer::incomingConnection(int socketDescriptor)
352 This method is invoked each time a new incoming connection is established with
353 the server. Clients must reimplement this function in their QUnixSocketServer
354 derived class to handle the connection.
356 A common approach to handling the connection is to pass \a socketDescriptor to
357 a QUnixSocket instance.
362 void QUnixSocketServerPrivate::acceptActivated()
365 socklen_t len = sizeof(sockaddr_un);
366 int connsock = ::accept(fd, (sockaddr *)&r, &len);
367 #ifdef QUNIXSOCKETSERVER_DEBUG
368 qDebug() << "QUnixSocketServer: Accept connection " << connsock;
371 me->incomingConnection(connsock);
376 #include "qunixsocketserver.moc"