source: trunk/src/network/socket/qlocalsocket_unix.cpp@ 318

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

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 18.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtNetwork module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qlocalsocket.h"
43#include "qlocalsocket_p.h"
44
45#ifndef QT_NO_LOCALSOCKET
46
47#include <sys/types.h>
48#include <sys/socket.h>
49#include <sys/un.h>
50#include <unistd.h>
51#include <fcntl.h>
52#include <errno.h>
53
54#include <qdatetime.h>
55#include <qdir.h>
56#include <qdebug.h>
57
58#define QT_CONNECT_TIMEOUT 30000
59
60QT_BEGIN_NAMESPACE
61
62QLocalSocketPrivate::QLocalSocketPrivate() : QIODevicePrivate(),
63 delayConnect(0),
64 connectTimer(0),
65 connectingSocket(-1),
66 connectingOpenMode(0),
67 state(QLocalSocket::UnconnectedState)
68{
69}
70
71void QLocalSocketPrivate::init()
72{
73 Q_Q(QLocalSocket);
74 // QIODevice signals
75 q->connect(&unixSocket, SIGNAL(aboutToClose()), q, SIGNAL(aboutToClose()));
76 q->connect(&unixSocket, SIGNAL(bytesWritten(qint64)),
77 q, SIGNAL(bytesWritten(qint64)));
78 q->connect(&unixSocket, SIGNAL(readyRead()), q, SIGNAL(readyRead()));
79 // QAbstractSocket signals
80 q->connect(&unixSocket, SIGNAL(connected()), q, SIGNAL(connected()));
81 q->connect(&unixSocket, SIGNAL(disconnected()), q, SIGNAL(disconnected()));
82 q->connect(&unixSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
83 q, SLOT(_q_stateChanged(QAbstractSocket::SocketState)));
84 q->connect(&unixSocket, SIGNAL(error(QAbstractSocket::SocketError)),
85 q, SLOT(_q_error(QAbstractSocket::SocketError)));
86 q->connect(&unixSocket, SIGNAL(readChannelFinished()), q, SIGNAL(readChannelFinished()));
87 unixSocket.setParent(q);
88}
89
90void QLocalSocketPrivate::_q_error(QAbstractSocket::SocketError socketError)
91{
92 Q_Q(QLocalSocket);
93 QString function = QLatin1String("QLocalSocket");
94 QLocalSocket::LocalSocketError error = (QLocalSocket::LocalSocketError)socketError;
95 QString errorString = generateErrorString(error, function);
96 q->setErrorString(errorString);
97 emit q->error(error);
98}
99
100void QLocalSocketPrivate::_q_stateChanged(QAbstractSocket::SocketState newState)
101{
102 Q_Q(QLocalSocket);
103 QLocalSocket::LocalSocketState currentState = state;
104 switch(newState) {
105 case QAbstractSocket::UnconnectedState:
106 state = QLocalSocket::UnconnectedState;
107 serverName = QString();
108 fullServerName = QString();
109 break;
110 case QAbstractSocket::ConnectingState:
111 state = QLocalSocket::ConnectingState;
112 break;
113 case QAbstractSocket::ConnectedState:
114 state = QLocalSocket::ConnectedState;
115 break;
116 case QAbstractSocket::ClosingState:
117 state = QLocalSocket::ClosingState;
118 break;
119 default:
120#if defined QLOCALSOCKET_DEBUG
121 qWarning() << "QLocalSocket::Unhandled socket state change:" << newState;
122#endif
123 return;
124 }
125 if (currentState != state)
126 emit q->stateChanged(state);
127}
128
129QString QLocalSocketPrivate::generateErrorString(QLocalSocket::LocalSocketError error, const QString &function) const
130{
131 QString errorString;
132 switch (error) {
133 case QLocalSocket::ConnectionRefusedError:
134 errorString = QLocalSocket::tr("%1: Connection refused").arg(function);
135 break;
136 case QLocalSocket::PeerClosedError:
137 errorString = QLocalSocket::tr("%1: Remote closed").arg(function);
138 break;
139 case QLocalSocket::ServerNotFoundError:
140 errorString = QLocalSocket::tr("%1: Invalid name").arg(function);
141 break;
142 case QLocalSocket::SocketAccessError:
143 errorString = QLocalSocket::tr("%1: Socket access error").arg(function);
144 break;
145 case QLocalSocket::SocketResourceError:
146 errorString = QLocalSocket::tr("%1: Socket resource error").arg(function);
147 break;
148 case QLocalSocket::SocketTimeoutError:
149 errorString = QLocalSocket::tr("%1: Socket operation timed out").arg(function);
150 break;
151 case QLocalSocket::DatagramTooLargeError:
152 errorString = QLocalSocket::tr("%1: Datagram too large").arg(function);
153 break;
154 case QLocalSocket::ConnectionError:
155 errorString = QLocalSocket::tr("%1: Connection error").arg(function);
156 break;
157 case QLocalSocket::UnsupportedSocketOperationError:
158 errorString = QLocalSocket::tr("%1: The socket operation is not supported").arg(function);
159 break;
160 case QLocalSocket::UnknownSocketError:
161 default:
162 errorString = QLocalSocket::tr("%1: Unknown error %2").arg(function).arg(errno);
163 }
164 return errorString;
165}
166
167void QLocalSocketPrivate::errorOccurred(QLocalSocket::LocalSocketError error, const QString &function)
168{
169 Q_Q(QLocalSocket);
170 switch (error) {
171 case QLocalSocket::ConnectionRefusedError:
172 unixSocket.setSocketError(QAbstractSocket::ConnectionRefusedError);
173 break;
174 case QLocalSocket::PeerClosedError:
175 unixSocket.setSocketError(QAbstractSocket::RemoteHostClosedError);
176 break;
177 case QLocalSocket::ServerNotFoundError:
178 unixSocket.setSocketError(QAbstractSocket::HostNotFoundError);
179 break;
180 case QLocalSocket::SocketAccessError:
181 unixSocket.setSocketError(QAbstractSocket::SocketAccessError);
182 break;
183 case QLocalSocket::SocketResourceError:
184 unixSocket.setSocketError(QAbstractSocket::SocketResourceError);
185 break;
186 case QLocalSocket::SocketTimeoutError:
187 unixSocket.setSocketError(QAbstractSocket::SocketTimeoutError);
188 break;
189 case QLocalSocket::DatagramTooLargeError:
190 unixSocket.setSocketError(QAbstractSocket::DatagramTooLargeError);
191 break;
192 case QLocalSocket::ConnectionError:
193 unixSocket.setSocketError(QAbstractSocket::NetworkError);
194 break;
195 case QLocalSocket::UnsupportedSocketOperationError:
196 unixSocket.setSocketError(QAbstractSocket::UnsupportedSocketOperationError);
197 break;
198 case QLocalSocket::UnknownSocketError:
199 default:
200 unixSocket.setSocketError(QAbstractSocket::UnknownSocketError);
201 }
202
203 QString errorString = generateErrorString(error, function);
204 q->setErrorString(errorString);
205 emit q->error(error);
206
207 // errors cause a disconnect
208 unixSocket.setSocketState(QAbstractSocket::UnconnectedState);
209 bool stateChanged = (state != QLocalSocket::UnconnectedState);
210 state = QLocalSocket::UnconnectedState;
211 q->close();
212 if (stateChanged)
213 q->emit stateChanged(state);
214}
215
216void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
217{
218 Q_D(QLocalSocket);
219 if (state() == ConnectedState
220 || state() == ConnectingState)
221 return;
222
223 d->errorString = QString();
224 d->unixSocket.setSocketState(QAbstractSocket::ConnectingState);
225 d->state = ConnectingState;
226 emit stateChanged(d->state);
227
228 if (name.isEmpty()) {
229 d->errorOccurred(ServerNotFoundError,
230 QLatin1String("QLocalSocket::connectToServer"));
231 return;
232 }
233
234 // create the socket
235 if (-1 == (d->connectingSocket = qSocket(PF_UNIX, SOCK_STREAM, 0))) {
236 d->errorOccurred(UnsupportedSocketOperationError,
237 QLatin1String("QLocalSocket::connectToServer"));
238 return;
239 }
240
241 // set non blocking so we can try to connect and it wont wait
242 int flags = fcntl(d->connectingSocket, F_GETFL, 0);
243 if (-1 == flags
244 || -1 == (fcntl(d->connectingSocket, F_SETFL, flags | O_NONBLOCK))) {
245 d->errorOccurred(UnknownSocketError,
246 QLatin1String("QLocalSocket::connectToServer"));
247 return;