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

Last change on this file since 187 was 157, checked in by Dmitry A. Kuminov, 16 years ago

network: Implemented QLocalServer/QLocalSocket/QNativeSocketEngine OS/2 bits (basically a copy of the Unix port with IPv6 stuff removed).

File size: 7.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** Copyright (C) 2009 netlabs.org. OS/2 parts.
7**
8** This file is part of the QtNetwork module of the Qt Toolkit.
9**
10** $QT_BEGIN_LICENSE:LGPL$
11** Commercial Usage
12** Licensees holding valid Qt Commercial licenses may use this file in
13** accordance with the Qt Commercial License Agreement provided with the
14** Software or, alternatively, in accordance with the terms contained in
15** a written agreement between you and Nokia.
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, Nokia gives you certain
26** additional rights. These rights are described in the Nokia Qt LGPL
27** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
28** 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 are unsure which license is appropriate for your use, please
39** contact the sales department 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 = qSocket(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 == qBind(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 == qListen(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_socketActivated()));
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->deleteLater();
155 socketNotifier = 0;
156
157 if (!fullServerName.isEmpty())
158 QFile::remove(fullServerName);
159}
160
161/*!
162 \internal
163
164 We have received a notification that we can read on the listen socket.
165 Accept the new socket.
166 */
167void QLocalServerPrivate::_q_socketActivated()
168{
169 Q_Q(QLocalServer);
170 if (-1 == listenSocket)
171 return;
172
173 ::sockaddr_un addr;
174 QT_SOCKLEN_T length = sizeof(sockaddr_un);
175 int connectedSocket = qAccept(listenSocket, (sockaddr *)&addr, &length);
176 if(-1 == connectedSocket) {
177 setError(QLatin1String("QLocalSocket::activated"));
178 closeServer();
179 } else {
180 socketNotifier->setEnabled(pendingConnections.size()
181 <= maxPendingConnections);
182 q->incomingConnection(connectedSocket);
183 }
184}
185
186void QLocalServerPrivate::waitForNewConnection(int msec, bool *timedOut)
187{
188 fd_set readfds;
189 FD_ZERO(&readfds);
190 FD_SET(listenSocket, &readfds);
191
192 timeval timeout;
193 timeout.tv_sec = msec / 1000;
194 timeout.tv_usec = (msec % 1000) * 1000;
195
196 // timeout can not be 0 or else select will return an error.
197 if (0 == msec)
198 timeout.tv_usec = 1000;
199
200 int result = -1;
201 // on Linux timeout will be updated by select, but _not_ on other systems.
202 QTime timer;
203 timer.start();
204 while (pendingConnections.isEmpty() && (-1 == msec || timer.elapsed() < msec)) {
205 result = ::select(listenSocket + 1, &readfds, 0, 0, &timeout);
206 if (-1 == result && errno != EINTR) {
207 setError(QLatin1String("QLocalServer::waitForNewConnection"));
208 closeServer();
209 break;
210 }
211 if (result > 0)
212 _q_socketActivated();
213 }
214 if (timedOut)
215 *timedOut = (result == 0);
216}
217
218void QLocalServerPrivate::setError(const QString &function)
219{
220 if (EAGAIN == errno)
221 return;
222
223 switch (errno) {
224 case EACCES:
225 errorString = QLocalServer::tr("%1: Permission denied").arg(function);
226 error = QAbstractSocket::SocketAccessError;
227 break;
228 case ELOOP:
229 case ENOENT:
230 case ENAMETOOLONG:
231 case EROFS:
232 case ENOTDIR:
233 errorString = QLocalServer::tr("%1: Name error").arg(function);
234 error = QAbstractSocket::HostNotFoundError;
235 break;
236 case EADDRINUSE:
237 errorString = QLocalServer::tr("%1: Address in use").arg(function);
238 error = QAbstractSocket::AddressInUseError;
239 break;
240
241 default:
242 errorString = QLocalServer::tr("%1: Unknown error %2")
243 .arg(function).arg(errno);
244 error = QAbstractSocket::UnknownSocketError;
245#if defined QLOCALSERVER_DEBUG
246 qWarning() << errorString << "fullServerName:" << fullServerName;
247#endif
248 }
249}
250
251QT_END_NAMESPACE
252
253#endif // QT_NO_LOCALSERVER
Note: See TracBrowser for help on using the repository browser.