source: trunk/src/network/socket/qlocalsocket_tcp.cpp@ 561

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

trunk: Merged in qt 4.6.1 sources.

File size: 14.2 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** This file is part of the QtNetwork module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
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.
23**
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.
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 have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qlocalsocket.h"
43#include "qlocalsocket_p.h"
44#include "qlocalserver.h"
45
46#include <qhostaddress.h>
47#include <qsettings.h>
48#include <qdebug.h>
49
50QT_BEGIN_NAMESPACE
51
52QLocalSocketPrivate::QLocalSocketPrivate() : QIODevicePrivate(),
53 tcpSocket(0),
54 ownsTcpSocket(true),
55 state(QLocalSocket::UnconnectedState)
56{
57}
58
59void QLocalSocketPrivate::init()
60{
61 setSocket(new QLocalUnixSocket);
62}
63
64void QLocalSocketPrivate::setSocket(QLocalUnixSocket* socket)
65{
66 if (ownsTcpSocket)
67 delete tcpSocket;
68 ownsTcpSocket = false;
69 tcpSocket = socket;
70
71 Q_Q(QLocalSocket);
72 // QIODevice signals
73 q->connect(tcpSocket, SIGNAL(aboutToClose()), q, SIGNAL(aboutToClose()));
74 q->connect(tcpSocket, SIGNAL(bytesWritten(qint64)),
75 q, SIGNAL(bytesWritten(qint64)));
76 q->connect(tcpSocket, SIGNAL(readyRead()), q, SIGNAL(readyRead()));
77 // QAbstractSocket signals
78 q->connect(tcpSocket, SIGNAL(connected()), q, SIGNAL(connected()));
79 q->connect(tcpSocket, SIGNAL(disconnected()), q, SIGNAL(disconnected()));
80 q->connect(tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
81 q, SLOT(_q_stateChanged(QAbstractSocket::SocketState)));
82 q->connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
83 q, SLOT(_q_error(QAbstractSocket::SocketError)));
84 q->connect(tcpSocket, SIGNAL(readChannelFinished()), q, SIGNAL(readChannelFinished()));
85 tcpSocket->setParent(q);
86}
87
88void QLocalSocketPrivate::_q_error(QAbstractSocket::SocketError socketError)
89{
90 Q_Q(QLocalSocket);
91 QString function = QLatin1String("QLocalSocket");
92 QLocalSocket::LocalSocketError error = (QLocalSocket::LocalSocketError)socketError;
93 QString errorString = generateErrorString(error, function);
94 q->setErrorString(errorString);
95 emit q->error(error);
96}
97
98void QLocalSocketPrivate::_q_stateChanged(QAbstractSocket::SocketState newState)
99{
100 Q_Q(QLocalSocket);
101 QLocalSocket::LocalSocketState currentState = state;
102 switch(newState) {
103 case QAbstractSocket::UnconnectedState:
104 state = QLocalSocket::UnconnectedState;
105 serverName = QString();
106 fullServerName = QString();
107 break;
108 case QAbstractSocket::ConnectingState:
109 state = QLocalSocket::ConnectingState;
110 break;
111 case QAbstractSocket::ConnectedState:
112 state = QLocalSocket::ConnectedState;
113 break;
114 case QAbstractSocket::ClosingState:
115 state = QLocalSocket::ClosingState;
116 break;
117 default:
118#if defined QLOCALSOCKET_DEBUG
119 qWarning() << "QLocalSocket::Unhandled socket state change:" << newState;
120#endif
121 return;
122 }
123 if (currentState != state)
124 emit q->stateChanged(state);
125}
126
127QString QLocalSocketPrivate::generateErrorString(QLocalSocket::LocalSocketError error, const QString &function) const
128{
129 QString errorString;
130 switch (error) {
131 case QLocalSocket::ConnectionRefusedError:
132 errorString = QLocalSocket::tr("%1: Connection refused").arg(function);
133 break;
134 case QLocalSocket::PeerClosedError:
135 errorString = QLocalSocket::tr("%1: Remote closed").arg(function);
136 break;
137 case QLocalSocket::ServerNotFoundError:
138 errorString = QLocalSocket::tr("%1: Invalid name").arg(function);
139 break;
140 case QLocalSocket::SocketAccessError:
141 errorString = QLocalSocket::tr("%1: Socket access error").arg(function);
142 break;
143 case QLocalSocket::SocketResourceError:
144 errorString = QLocalSocket::tr("%1: Socket resource error").arg(function);
145 break;
146 case QLocalSocket::SocketTimeoutError:
147 errorString = QLocalSocket::tr("%1: Socket operation timed out").arg(function);
148 break;
149 case QLocalSocket::DatagramTooLargeError:
150 errorString = QLocalSocket::tr("%1: Datagram too large").arg(function);
151 break;
152 case QLocalSocket::ConnectionError:
153 errorString = QLocalSocket::tr("%1: Connection error").arg(function);
154 break;
155 case QLocalSocket::UnsupportedSocketOperationError:
156 errorString = QLocalSocket::tr("%1: The socket operation is not supported").arg(function);
157 break;
158 case QLocalSocket::UnknownSocketError:
159 default:
160 errorString = QLocalSocket::tr("%1: Unknown error").arg(function);
161 }
162 return errorString;
163}
164
165void QLocalSocketPrivate::errorOccurred(QLocalSocket::LocalSocketError error, const QString &function)
166{
167 Q_Q(QLocalSocket);
168 switch (error) {
169 case QLocalSocket::ConnectionRefusedError:
170 tcpSocket->setSocketError(QAbstractSocket::ConnectionRefusedError);
171 break;
172 case QLocalSocket::PeerClosedError:
173 tcpSocket->setSocketError(QAbstractSocket::RemoteHostClosedError);
174 break;
175 case QLocalSocket::ServerNotFoundError:
176 tcpSocket->setSocketError(QAbstractSocket::HostNotFoundError);
177 break;
178 case QLocalSocket::SocketAccessError:
179 tcpSocket->setSocketError(QAbstractSocket::SocketAccessError);
180 break;
181 case QLocalSocket::SocketResourceError:
182 tcpSocket->setSocketError(QAbstractSocket::SocketResourceError);
183 break;
184 case QLocalSocket::SocketTimeoutError:
185 tcpSocket->setSocketError(QAbstractSocket::SocketTimeoutError);
186 break;
187 case QLocalSocket::DatagramTooLargeError:
188 tcpSocket->setSocketError(QAbstractSocket::DatagramTooLargeError);
189 break;
190 case QLocalSocket::ConnectionError:
191 tcpSocket->setSocketError(QAbstractSocket::NetworkError);
192 break;
193 case QLocalSocket::UnsupportedSocketOperationError:
194 tcpSocket->setSocketError(QAbstractSocket::UnsupportedSocketOperationError);
195 break;
196 case QLocalSocket::UnknownSocketError:
197 default:
198 tcpSocket->setSocketError(QAbstractSocket::UnknownSocketError);
199 }
200
201 QString errorString = generateErrorString(error, function);
202 q->setErrorString(errorString);
203 emit q->error(error);
204
205 // errors cause a disconnect
206 tcpSocket->setSocketState(QAbstractSocket::UnconnectedState);
207 bool stateChanged = (state != QLocalSocket::UnconnectedState);
208 state = QLocalSocket::UnconnectedState;
209 q->close();
210 if (stateChanged)
211 q->emit stateChanged(state);
212}
213
214void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
215{
216 Q_D(QLocalSocket);
217 if (state() == ConnectedState
218 || state() == ConnectingState)
219 return;
220
221 d->errorString = QString();
222 d->state = ConnectingState;
223 emit stateChanged(d->state);
224
225 if (name.isEmpty()) {
226 d->errorOccurred(ServerNotFoundError,
227 QLatin1String("QLocalSocket::connectToServer"));
228 return;
229 }
230
231 d->serverName = name;
232 const QLatin1String prefix("QLocalServer/");
233 if (name.startsWith(prefix))
234 d->fullServerName = name;
235 else
236 d->fullServerName = prefix + name;
237
238 QSettings settings(QLatin1String("Trolltech"), QLatin1String("Qt"));
239 bool ok;
240 const quint16 port = settings.value(d->fullServerName).toUInt(&ok);
241 if (!ok) {
242 d->errorOccurred(ServerNotFoundError,
243 QLatin1String("QLocalSocket::connectToServer"));
244 return;
245 }
246 d->tcpSocket->connectToHost(QHostAddress::LocalHost, port, openMode);
247 QIODevice::open(openMode);
248}
249
250bool QLocalSocket::setSocketDescriptor(quintptr socketDescriptor,
251 LocalSocketState socketState, OpenMode openMode)
252{
253 Q_D(QLocalSocket);
254 QAbstractSocket::SocketState newSocketState = QAbstractSocket::UnconnectedState;
255 switch (socketState) {
256 case ConnectingState:
257 newSocketState = QAbstractSocket::ConnectingState;
258 break;
259 case ConnectedState:
260 newSocketState = QAbstractSocket::ConnectedState;
261 break;
262 case ClosingState:
263 newSocketState = QAbstractSocket::ClosingState;
264 break;
265 case UnconnectedState:
266 newSocketState = QAbstractSocket::UnconnectedState;
267 break;
268 }
269 QIODevice::open(openMode);
270 d->state = socketState;
271
272 // Is our parent a localServer? Then it wants us to use its remote socket.
273 QLocalServer* localServer = qobject_cast<QLocalServer*>( parent() );
274 if (localServer) {
275 foreach (QObject* child, localServer->children()) {
276 QTcpSocket* childTcpSocket = qobject_cast<QTcpSocket*>(child);
277 if (childTcpSocket && childTcpSocket->socketDescriptor() == socketDescriptor) {
278 d->setSocket( static_cast<QLocalUnixSocket*>(childTcpSocket) );
279 return true;
280 }
281 }
282 }
283
284 // We couldn't find the socket in the children list of our server.
285 // So it might be that the user wants to set a socket descriptor.
286 return d->tcpSocket->setSocketDescriptor(socketDescriptor,
287 newSocketState, openMode);
288}
289
290quintptr QLocalSocket::socketDescriptor() const
291{
292 Q_D(const QLocalSocket);
293 return d->tcpSocket->socketDescriptor();
294}
295
296qint64 QLocalSocket::readData(char *data, qint64 c)
297{
298 Q_D(QLocalSocket);
299 return d->tcpSocket->readData(data, c);
300}
301
302qint64 QLocalSocket::writeData(const char *data, qint64 c)
303{
304 Q_D(QLocalSocket);
305 return d->tcpSocket->writeData(data, c);
306}
307
308void QLocalSocket::abort()
309{
310 Q_D(QLocalSocket);
311 d->tcpSocket->abort();
312}
313
314qint64 QLocalSocket::bytesAvailable() const
315{
316 Q_D(const QLocalSocket);
317 return QIODevice::bytesAvailable() + d->tcpSocket->bytesAvailable();
318}
319
320qint64 QLocalSocket::bytesToWrite() const
321{
322 Q_D(const QLocalSocket);
323 return d->tcpSocket->bytesToWrite();
324}
325
326bool QLocalSocket::canReadLine() const
327{
328 Q_D(const QLocalSocket);
329 return QIODevice::canReadLine() || d->tcpSocket->canReadLine();
330}
331
332void QLocalSocket::close()
333{
334 Q_D(QLocalSocket);
335 d->tcpSocket->close();
336 d->serverName = QString();
337 d->fullServerName = QString();
338 QIODevice::close();
339}
340
341bool QLocalSocket::waitForBytesWritten(int msecs)
342{
343 Q_D(QLocalSocket);
344 return d->tcpSocket->waitForBytesWritten(msecs);
345}
346
347bool QLocalSocket::flush()
348{
349 Q_D(QLocalSocket);
350 return d->tcpSocket->flush();
351}
352
353void QLocalSocket::disconnectFromServer()
354{
355 Q_D(QLocalSocket);
356 d->tcpSocket->disconnectFromHost();
357}
358
359QLocalSocket::LocalSocketError QLocalSocket::error() const
360{
361 Q_D(const QLocalSocket);
362 switch (d->tcpSocket->error()) {
363 case QAbstractSocket::ConnectionRefusedError:
364 return QLocalSocket::ConnectionRefusedError;
365 case QAbstractSocket::RemoteHostClosedError:
366 return QLocalSocket::PeerClosedError;
367 case QAbstractSocket::HostNotFoundError:
368 return QLocalSocket::ServerNotFoundError;
369 case QAbstractSocket::SocketAccessError:
370 return QLocalSocket::SocketAccessError;
371 case QAbstractSocket::SocketResourceError:
372 return QLocalSocket::SocketResourceError;
373 case QAbstractSocket::SocketTimeoutError:
374 return QLocalSocket::SocketTimeoutError;
375 case QAbstractSocket::DatagramTooLargeError:
376 return QLocalSocket::DatagramTooLargeError;
377 case QAbstractSocket::NetworkError:
378 return QLocalSocket::ConnectionError;
379 case QAbstractSocket::UnsupportedSocketOperationError:
380 return QLocalSocket::UnsupportedSocketOperationError;
381 case QAbstractSocket::UnknownSocketError:
382 return QLocalSocket::UnknownSocketError;
383 default:
384#if defined QLOCALSOCKET_DEBUG
385 qWarning() << "QLocalSocket error not handled:" << d->tcpSocket->error();
386#endif
387 break;
388 }
389 return UnknownSocketError;
390}
391
392bool QLocalSocket::isValid() const
393{
394 Q_D(const QLocalSocket);
395 return d->tcpSocket->isValid();
396}
397
398qint64 QLocalSocket::readBufferSize() const
399{
400 Q_D(const QLocalSocket);
401 return d->tcpSocket->readBufferSize();
402}
403
404void QLocalSocket::setReadBufferSize(qint64 size)
405{
406 Q_D(QLocalSocket);
407 d->tcpSocket->setReadBufferSize(size);
408}
409
410bool QLocalSocket::waitForConnected(int msec)
411{
412 Q_D(QLocalSocket);
413 if (state() != ConnectingState)
414 return (state() == ConnectedState);
415
416 return d->tcpSocket->waitForConnected(msec);
417}
418
419bool QLocalSocket::waitForDisconnected(int msecs)
420{
421 Q_D(QLocalSocket);
422 if (state() == UnconnectedState) {
423 qWarning() << "QLocalSocket::waitForDisconnected() is not allowed in UnconnectedState";
424 return false;
425 }
426 return (d->tcpSocket->waitForDisconnected(msecs));
427}
428
429bool QLocalSocket::waitForReadyRead(int msecs)
430{
431 Q_D(QLocalSocket);
432 if (state() == QLocalSocket::UnconnectedState)
433 return false;
434 return (d->tcpSocket->waitForReadyRead(msecs));
435}
436
437QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.