source: trunk/src/network/socket/qlocalserver_os2.cpp@ 603

Last change on this file since 603 was 568, checked in by Dmitry A. Kuminov, 15 years ago

network: Adopted to 4.6.1 changes.

File size: 7.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** Copyright (C) 2009 netlabs.org. OS/2 parts.
8**
9** This file is part of the QtNetwork module of the Qt Toolkit.
10**
11** $QT_BEGIN_LICENSE:LGPL$
12** Commercial Usage
13** Licensees holding valid Qt Commercial licenses may use this file in
14** accordance with the Qt Commercial License Agreement provided with the
15** Software or, alternatively, in accordance with the terms contained in
16** a written agreement between you and Nokia.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 2.1 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 2.1 requirements
24** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** In addition, as a special exception, Nokia gives you certain additional
27** rights. These rights are described in the Nokia Qt LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** GNU General Public License Usage
31** Alternatively, this file may be used under the terms of the GNU
32** General Public License version 3.0 as published by the Free Software
33** Foundation and appearing in the file LICENSE.GPL included in the
34** packaging of this file. Please review the following information to
35** ensure the GNU General Public License version 3.0 requirements will be
36** met: http://www.gnu.org/copyleft/gpl.html.
37**
38** If you have questions regarding the use of this file, please contact
39** Nokia at [email protected].
40** $QT_END_LICENSE$
41**
42****************************************************************************/
43
44#include "qlocalserver.h"
45#include "qlocalserver_p.h"
46#include "qlocalsocket.h"
47#include "qlocalsocket_p.h"
48
49#ifndef QT_NO_LOCALSERVER
50
51#include <sys/socket.h>
52#include <sys/un.h>
53
54#include <qdebug.h>
55#include <qdir.h>
56#include <qdatetime.h>
57
58QT_BEGIN_NAMESPACE
59
60void QLocalServerPrivate::init()
61{
62}
63
64bool QLocalServerPrivate::removeServer(const QString &name)
65{
66 QString fileName;
67 if (name.startsWith(QLatin1Char('/'))) {
68 fileName = name;
69 } else {
70 fileName = QDir::cleanPath(QDir::tempPath());
71 fileName += QLatin1Char('/') + name;
72 }
73 if (QFile::exists(fileName))
74 return QFile::remove(fileName);
75 else
76 return true;
77}
78
79bool QLocalServerPrivate::listen(const QString &requestedServerName)
80{
81 Q_Q(QLocalServer);
82
83 // determine the full server path
84 if (requestedServerName.startsWith(QLatin1Char('/'))) {
85 fullServerName = requestedServerName;
86 } else {
87 fullServerName = QDir::cleanPath(QDir::tempPath());
88 fullServerName += QLatin1Char('/') + requestedServerName;
89 }
90 serverName = requestedServerName;
91
92 // create the unix socket
93 listenSocket = ::socket(PF_UNIX, SOCK_STREAM, 0);
94 if (-1 == listenSocket) {
95 setError(QLatin1String("QLocalServer::listen"));
96 closeServer();
97 return false;
98 }
99
100 // Construct the unix address
101 struct ::sockaddr_un addr;
102 addr.sun_family = PF_UNIX;
103 if (sizeof(addr.sun_path) < (uint)fullServerName.toLatin1().size() + 1) {
104 setError(QLatin1String("QLocalServer::listen"));
105 closeServer();
106 return false;
107 }
108 ::memcpy(addr.sun_path, fullServerName.toLatin1().data(),
109 fullServerName.toLatin1().size() + 1);
110
111 // bind
112 if(-1 == ::bind(listenSocket, (sockaddr *)&addr, sizeof(sockaddr_un))) {
113 setError(QLatin1String("QLocalServer::listen"));
114 // if address is in use already, just close the socket, but do not delete the file
115 if(errno == EADDRINUSE)
116 QT_CLOSE(listenSocket);
117 // otherwise, close the socket and delete the file
118 else
119 closeServer();
120 listenSocket = -1;
121 return false;
122 }
123
124 // listen for connections
125 if (-1 == ::listen(listenSocket, 50)) {
126 setError(QLatin1String("QLocalServer::listen"));
127 closeServer();
128 listenSocket = -1;
129 if (error != QAbstractSocket::AddressInUseError)
130 QFile::remove(fullServerName);
131 return false;
132 }
133 Q_ASSERT(!socketNotifier);
134 socketNotifier = new QSocketNotifier(listenSocket,
135 QSocketNotifier::Read, q);
136 q->connect(socketNotifier, SIGNAL(activated(int)),
137 q, SLOT(_q_onNewConnection()));
138 socketNotifier->setEnabled(maxPendingConnections > 0);
139 return true;
140}
141
142/*!
143 \internal
144
145 \sa QLocalServer::closeServer()
146 */
147void QLocalServerPrivate::closeServer()
148{
149 if (-1 != listenSocket)
150 QT_CLOSE(listenSocket);
151 listenSocket = -1;
152
153 if (socketNotifier) {
154 socketNotifier->setEnabled(false); // Otherwise, closed socket is checked before deleter runs
155 socketNotifier->deleteLater();
156 socketNotifier = 0;
157 }
158
159 if (!fullServerName.isEmpty())
160 QFile::remove(fullServerName);
161}
162
163/*!
164 \internal
165
166 We have received a notification that we can read on the listen socket.
167 Accept the new socket.
168 */
169void QLocalServerPrivate::_q_onNewConnection()
170{
171 Q_Q(QLocalServer);
172 if (-1 == listenSocket)
173 return;
174
175 ::sockaddr_un addr;
176 int length = sizeof(sockaddr_un);
177 int connectedSocket = ::accept(listenSocket, (sockaddr *)&addr, &length);
178 if(-1 == connectedSocket) {
179 setError(QLatin1String("QLocalSocket::activated"));
180 closeServer();
181 } else {
182 socketNotifier->setEnabled(pendingConnections.size()
183 <= maxPendingConnections);
184 q->incomingConnection(connectedSocket);
185 }
186}
187
188void QLocalServerPrivate::waitForNewConnection(int msec, bool *timedOut)
189{
190 fd_set readfds;
191 FD_ZERO(&readfds);
192 FD_SET(listenSocket, &readfds);
193
194 timeval timeout;
195 timeout.tv_sec = msec / 1000;
196 timeout.tv_usec = (msec % 1000) * 1000;
197
198 int result = -1;
199 result = ::select(listenSocket + 1, &readfds, 0, 0, (msec == -1) ? 0 : &timeout);
200 if (-1 == result) {
201 setError(QLatin1String("QLocalServer::waitForNewConnection"));
202 closeServer();
203 }
204 if (result > 0)
205 _q_onNewConnection();
206 if (timedOut)
207 *timedOut = (result == 0);
208}
209
210void QLocalServerPrivate::setError(const QString &function)
211{
212 if (EAGAIN == errno)
213 return;
214
215 switch (errno) {
216 case EACCES:
217 errorString = QLocalServer::tr("%1: Permission denied").arg(function);
218 error = QAbstractSocket::SocketAccessError;
219 break;
220 case ELOOP:
221 case ENOENT:
222 case ENAMETOOLONG:
223 case EROFS:
224 case ENOTDIR:
225 errorString = QLocalServer::tr("%1: Name error").arg(function);
226 error = QAbstractSocket::HostNotFoundError;
227 break;
228 case EADDRINUSE:
229 errorString = QLocalServer::tr("%1: Address in use").arg(function);
230 error = QAbstractSocket::AddressInUseError;
231 break;
232
233 default:
234 errorString = QLocalServer::tr("%1: Unknown error %2")
235 .arg(function).arg(errno);
236 error = QAbstractSocket::UnknownSocketError;
237#if defined QLOCALSERVER_DEBUG
238 qWarning() << errorString << "fullServerName:" << fullServerName;
239#endif
240 }
241}
242
243QT_END_NAMESPACE
244
245#endif // QT_NO_LOCALSERVER
Note: See TracBrowser for help on using the repository browser.