Qt 4.8
qlocalserver_unix.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qlocalserver.h"
43 #include "qlocalserver_p.h"
44 #include "qlocalsocket.h"
45 #include "qlocalsocket_p.h"
46 #include "qnet_unix_p.h"
47 
48 #ifndef QT_NO_LOCALSERVER
49 
50 #include <sys/socket.h>
51 #include <sys/un.h>
52 
53 #include <qdebug.h>
54 #include <qdir.h>
55 #include <qdatetime.h>
56 
57 #ifdef Q_OS_VXWORKS
58 # include <selectLib.h>
59 #endif
60 
62 
64 {
65 }
66 
68 {
70  if (name.startsWith(QLatin1Char('/'))) {
71  fileName = name;
72  } else {
73  fileName = QDir::cleanPath(QDir::tempPath());
74  fileName += QLatin1Char('/') + name;
75  }
76  if (QFile::exists(fileName))
77  return QFile::remove(fileName);
78  else
79  return true;
80 }
81 
82 bool QLocalServerPrivate::listen(const QString &requestedServerName)
83 {
85 
86  // determine the full server path
87  if (requestedServerName.startsWith(QLatin1Char('/'))) {
88  fullServerName = requestedServerName;
89  } else {
91  fullServerName += QLatin1Char('/') + requestedServerName;
92  }
93  serverName = requestedServerName;
94 
95  // create the unix socket
96  listenSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0);
97  if (-1 == listenSocket) {
98  setError(QLatin1String("QLocalServer::listen"));
99  closeServer();
100  return false;
101  }
102 
103  // Construct the unix address
104  struct ::sockaddr_un addr;
105  addr.sun_family = PF_UNIX;
106  if (sizeof(addr.sun_path) < (uint)fullServerName.toLatin1().size() + 1) {
107  setError(QLatin1String("QLocalServer::listen"));
108  closeServer();
109  return false;
110  }
111  ::memcpy(addr.sun_path, fullServerName.toLatin1().data(),
112  fullServerName.toLatin1().size() + 1);
113 
114 #ifdef Q_OS_SYMBIAN
115  // In SYMBIAN OS it can currently happen that accept is called twice,
116  // once from waitForNewConnection and once via QSocketNotfier activity
117  //
118  // As an workaround, we set the socket to non blocking so possible
119  // subsequent call to accept will not block in any case
120  //
121  // This change can be removed once more generic fix to select thread
122  // synchronization problem is implemented.
123  int flags = fcntl(listenSocket, F_GETFL, 0);
124  if (-1 == flags
125  || -1 == (fcntl(listenSocket, F_SETFL, flags | O_NONBLOCK))) {
126  setError(QLatin1String("QLocalServer::listen"));
127  closeServer();
128  return false;
129  }
130 #endif
131 
132  // bind
133  if(-1 == QT_SOCKET_BIND(listenSocket, (sockaddr *)&addr, sizeof(sockaddr_un))) {
134  setError(QLatin1String("QLocalServer::listen"));
135  // if address is in use already, just close the socket, but do not delete the file
136  if(errno == EADDRINUSE)
137  QT_CLOSE(listenSocket);
138  // otherwise, close the socket and delete the file
139  else
140  closeServer();
141  listenSocket = -1;
142  return false;
143  }
144 
145  // listen for connections
146  if (-1 == qt_safe_listen(listenSocket, 50)) {
147  setError(QLatin1String("QLocalServer::listen"));
148  closeServer();
149  listenSocket = -1;
152  return false;
153  }
154  Q_ASSERT(!socketNotifier);
155  socketNotifier = new QSocketNotifier(listenSocket,
157  q->connect(socketNotifier, SIGNAL(activated(int)),
158  q, SLOT(_q_onNewConnection()));
159  socketNotifier->setEnabled(maxPendingConnections > 0);
160  return true;
161 }
162 
169 {
170  if (socketNotifier) {
171  socketNotifier->setEnabled(false); // Otherwise, closed socket is checked before deleter runs
172  socketNotifier->deleteLater();
173  socketNotifier = 0;
174  }
175 
176  if (-1 != listenSocket)
177  QT_CLOSE(listenSocket);
178  listenSocket = -1;
179 
180  if (!fullServerName.isEmpty())
182 }
183 
194 {
195  Q_Q(QLocalServer);
196  if (-1 == listenSocket)
197  return;
198 
199  ::sockaddr_un addr;
200  QT_SOCKLEN_T length = sizeof(sockaddr_un);
201  int connectedSocket = qt_safe_accept(listenSocket, (sockaddr *)&addr, &length);
202  if(-1 == connectedSocket) {
203  setError(QLatin1String("QLocalSocket::activated"));
204  closeServer();
205  } else {
206  socketNotifier->setEnabled(pendingConnections.size()
208  q->incomingConnection(connectedSocket);
209  }
210 }
211 
212 void QLocalServerPrivate::waitForNewConnection(int msec, bool *timedOut)
213 {
214  fd_set readfds;
215  FD_ZERO(&readfds);
216  FD_SET(listenSocket, &readfds);
217 
218  timeval timeout;
219  timeout.tv_sec = msec / 1000;
220  timeout.tv_usec = (msec % 1000) * 1000;
221 
222  int result = -1;
223  result = qt_safe_select(listenSocket + 1, &readfds, 0, 0, (msec == -1) ? 0 : &timeout);
224  if (-1 == result) {
225  setError(QLatin1String("QLocalServer::waitForNewConnection"));
226  closeServer();
227  }
228  if (result > 0)
230  if (timedOut)
231  *timedOut = (result == 0);
232 }
233 
235 {
236  if (EAGAIN == errno)
237  return;
238 
239  switch (errno) {
240  case EACCES:
241  errorString = QLocalServer::tr("%1: Permission denied").arg(function);
243  break;
244  case ELOOP:
245  case ENOENT:
246  case ENAMETOOLONG:
247  case EROFS:
248  case ENOTDIR:
249  errorString = QLocalServer::tr("%1: Name error").arg(function);
251  break;
252  case EADDRINUSE:
253  errorString = QLocalServer::tr("%1: Address in use").arg(function);
255  break;
256 
257  default:
258  errorString = QLocalServer::tr("%1: Unknown error %2")
259  .arg(function).arg(errno);
261 #if defined QLOCALSERVER_DEBUG
262  qWarning() << errorString << "fullServerName:" << fullServerName;
263 #endif
264  }
265 }
266 
268 
269 #endif // QT_NO_LOCALSERVER
bool listen(const QString &name)
void waitForNewConnection(int msec, bool *timedOut)
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
#define SLOT(a)
Definition: qobjectdefs.h:226
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
#define QT_SOCKLEN_T
#define Q_Q(Class)
Definition: qglobal.h:2483
bool exists() const
Returns true if the file specified by fileName() exists; otherwise returns false. ...
Definition: qfile.cpp:626
void _q_onNewConnection()
We have received a notification that we can read on the listen socket.
#define SIGNAL(a)
Definition: qobjectdefs.h:227
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QQueue< QLocalSocket * > pendingConnections
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
const char * name
Q_CORE_EXPORT void qWarning(const char *,...)
The QLocalServer class provides a local socket based server.
Definition: qlocalserver.h:58
unsigned int uint
Definition: qglobal.h:996
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
static QString cleanPath(const QString &path)
Removes all multiple directory separators "/" and resolves any "."s or ".."s found in the path...
Definition: qdir.cpp:2082
void setError(const QString &function)
static QString tempPath()
Returns the absolute path of the system&#39;s temporary directory.
Definition: qdir.cpp:1987
int fcntl(int, int,...)
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, const struct timeval *orig_timeout)
Definition: qcore_unix.cpp:73
static int qt_safe_socket(int domain, int type, int protocol, int flags=0)
Definition: qnet_unix_p.h:83
static int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen, int flags=0)
Definition: qnet_unix_p.h:111
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
QAbstractSocket::SocketError error
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
static int qt_safe_listen(int s, int backlog)
Definition: qnet_unix_p.h:140
bool remove()
Removes the file specified by fileName().
Definition: qfile.cpp:715
static QString fileName(const QString &fileUrl)
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
int errno
static bool removeServer(const QString &name)
#define QT_CLOSE
Definition: qcore_unix_p.h:304