Qt 4.8
qlocalsocket_tcp.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 "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 
51 
53  tcpSocket(0),
54  ownsTcpSocket(true),
55  state(QLocalSocket::UnconnectedState)
56 {
57 }
58 
60 {
61  setSocket(new QLocalUnixSocket);
62 }
63 
64 void QLocalSocketPrivate::setSocket(QLocalUnixSocket* socket)
65 {
66  if (ownsTcpSocket)
67  delete tcpSocket;
68  ownsTcpSocket = false;
69  tcpSocket = socket;
70 
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 
88 void QLocalSocketPrivate::_q_error(QAbstractSocket::SocketError socketError)
89 {
91  QString function = QLatin1String("QLocalSocket");
93  QString errorString = generateErrorString(error, function);
94  q->setErrorString(errorString);
95  emit q->error(error);
96 }
97 
98 void QLocalSocketPrivate::_q_stateChanged(QAbstractSocket::SocketState newState)
99 {
100  Q_Q(QLocalSocket);
101  QLocalSocket::LocalSocketState currentState = state;
102  switch(newState) {
105  serverName.clear();
107  break;
110  break;
113  break;
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 
127 QString QLocalSocketPrivate::generateErrorString(QLocalSocket::LocalSocketError error, const QString &function) const
128 {
130  switch (error) {
132  errorString = QLocalSocket::tr("%1: Connection refused").arg(function);
133  break;
135  errorString = QLocalSocket::tr("%1: Remote closed").arg(function);
136  break;
138  errorString = QLocalSocket::tr("%1: Invalid name").arg(function);
139  break;
141  errorString = QLocalSocket::tr("%1: Socket access error").arg(function);
142  break;
144  errorString = QLocalSocket::tr("%1: Socket resource error").arg(function);
145  break;
147  errorString = QLocalSocket::tr("%1: Socket operation timed out").arg(function);
148  break;
150  errorString = QLocalSocket::tr("%1: Datagram too large").arg(function);
151  break;
153  errorString = QLocalSocket::tr("%1: Connection error").arg(function);
154  break;
156  errorString = QLocalSocket::tr("%1: The socket operation is not supported").arg(function);
157  break;
159  default:
160  errorString = QLocalSocket::tr("%1: Unknown error").arg(function);
161  }
162  return errorString;
163 }
164 
165 void QLocalSocketPrivate::errorOccurred(QLocalSocket::LocalSocketError error, const QString &function)
166 {
167  Q_Q(QLocalSocket);
168  switch (error) {
170  tcpSocket->setSocketError(QAbstractSocket::ConnectionRefusedError);
171  break;
173  tcpSocket->setSocketError(QAbstractSocket::RemoteHostClosedError);
174  break;
176  tcpSocket->setSocketError(QAbstractSocket::HostNotFoundError);
177  break;
179  tcpSocket->setSocketError(QAbstractSocket::SocketAccessError);
180  break;
182  tcpSocket->setSocketError(QAbstractSocket::SocketResourceError);
183  break;
185  tcpSocket->setSocketError(QAbstractSocket::SocketTimeoutError);
186  break;
188  tcpSocket->setSocketError(QAbstractSocket::DatagramTooLargeError);
189  break;
191  tcpSocket->setSocketError(QAbstractSocket::NetworkError);
192  break;
194  tcpSocket->setSocketError(QAbstractSocket::UnsupportedSocketOperationError);
195  break;
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);
209  q->close();
210  if (stateChanged)
211  q->emit stateChanged(state);
212 }
213 
215 {
216  Q_D(QLocalSocket);
217  if (state() == ConnectedState
218  || state() == ConnectingState)
219  return;
220 
221  d->errorString.clear();
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 
251  LocalSocketState socketState, OpenMode openMode)
252 {
253  Q_D(QLocalSocket);
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 
291 {
292  Q_D(const QLocalSocket);
293  return d->tcpSocket->socketDescriptor();
294 }
295 
297 {
298  Q_D(QLocalSocket);
299  return d->tcpSocket->readData(data, c);
300 }
301 
303 {
304  Q_D(QLocalSocket);
305  return d->tcpSocket->writeData(data, c);
306 }
307 
309 {
310  Q_D(QLocalSocket);
311  d->tcpSocket->abort();
312 }
313 
315 {
316  Q_D(const QLocalSocket);
317  return QIODevice::bytesAvailable() + d->tcpSocket->bytesAvailable();
318 }
319 
321 {
322  Q_D(const QLocalSocket);
323  return d->tcpSocket->bytesToWrite();
324 }
325 
327 {
328  Q_D(const QLocalSocket);
329  return QIODevice::canReadLine() || d->tcpSocket->canReadLine();
330 }
331 
333 {
334  Q_D(QLocalSocket);
335  d->tcpSocket->close();
336  d->serverName.clear();
337  d->fullServerName.clear();
339 }
340 
342 {
343  Q_D(QLocalSocket);
344  return d->tcpSocket->waitForBytesWritten(msecs);
345 }
346 
348 {
349  Q_D(QLocalSocket);
350  return d->tcpSocket->flush();
351 }
352 
354 {
355  Q_D(QLocalSocket);
356  d->tcpSocket->disconnectFromHost();
357 }
358 
360 {
361  Q_D(const QLocalSocket);
362  switch (d->tcpSocket->error()) {
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 
393 {
394  Q_D(const QLocalSocket);
395  return d->tcpSocket->isValid();
396 }
397 
399 {
400  Q_D(const QLocalSocket);
401  return d->tcpSocket->readBufferSize();
402 }
403 
405 {
406  Q_D(QLocalSocket);
407  d->tcpSocket->setReadBufferSize(size);
408 }
409 
411 {
412  Q_D(QLocalSocket);
413  if (state() != ConnectingState)
414  return (state() == ConnectedState);
415 
416  return d->tcpSocket->waitForConnected(msec);
417 }
418 
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 
430 {
431  Q_D(QLocalSocket);
433  return false;
434  return (d->tcpSocket->waitForReadyRead(msecs));
435 }
436 
T qobject_cast(QObject *object)
Definition: qobject.h:375
double d
Definition: qnumeric_p.h:62
quintptr socketDescriptor() const
Returns the native socket descriptor of the QLocalSocket object if this is available; otherwise retur...
int socketDescriptor() const
Returns the native socket descriptor of the QAbstractSocket object if this is available; otherwise re...
bool waitForReadyRead(int msecs=30000)
This function blocks until data is available for reading and the QIODevice::readyRead() signal has be...
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Returns the value for setting key.
Definition: qsettings.cpp:3460
QIntegerForSizeof< void * >::Unsigned quintptr
Definition: qglobal.h:986
unsigned char c[8]
Definition: qnumeric_p.h:62
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
LocalSocketState
This enum describes the different states in which a socket can be.
Definition: qlocalsocket.h:78
bool waitForConnected(int msecs=30000)
Waits until the socket is connected, up to msecs milliseconds.
QIODevice::OpenMode openMode
Definition: qiodevice_p.h:212
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
Definition: qiodevice.cpp:590
The QSettings class provides persistent platform-independent application settings.
Definition: qsettings.h:73
QLocalSocket::LocalSocketState state
#define SLOT(a)
Definition: qobjectdefs.h:226
virtual void close()
Reimplemented Function
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
bool waitForDisconnected(int msecs=30000)
Waits until the socket has disconnected, up to msecs milliseconds.
The QString class provides a Unicode character string.
Definition: qstring.h:83
virtual qint64 writeData(const char *, qint64)
Reimplemented Function
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
QLocalSocket::LocalSocketError error
#define Q_D(Class)
Definition: qglobal.h:2482
The QLocalSocket class provides a local socket.
Definition: qlocalsocket.h:58
qint64 readBufferSize() const
Returns the size of the internal read buffer.
#define Q_Q(Class)
Definition: qglobal.h:2483
SocketState
This enum describes the different states in which a socket can be.
#define SIGNAL(a)
Definition: qobjectdefs.h:227
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static QIntfbScreen * connected
virtual qint64 readData(char *, qint64)
Reimplemented Function
void setReadBufferSize(qint64 size)
Sets the size of QLocalSocket&#39;s internal read buffer to be size bytes.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
const char * name
#define emit
Definition: qobjectdefs.h:76
SocketError
This enum describes the socket errors that can occur.
unsigned short quint16
Definition: qglobal.h:936
Q_CORE_EXPORT void qWarning(const char *,...)
bool flush()
This function writes as much as possible from the internal write buffer to the socket, without blocking.
The QLocalServer class provides a local socket based server.
Definition: qlocalserver.h:58
static const char * data(const QByteArray &arr)
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
void connectToServer(const QString &name, OpenMode openMode=ReadWrite)
Attempts to make a connection to name.
The QTcpSocket class provides a TCP socket.
Definition: qtcpsocket.h:56
QString errorString
Definition: qiodevice_p.h:213
__int64 qint64
Definition: qglobal.h:942
LocalSocketError error() const
Returns the type of error that last occurred.
virtual qint64 bytesToWrite() const
Reimplemented Function
bool isValid() const
Returns true if the socket is valid and ready for use; otherwise returns false.
virtual bool canReadLine() const
Reimplemented Function
void abort()
Aborts the current connection and resets the socket.
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
bool waitForBytesWritten(int msecs=30000)
Reimplemented Function
uint toUInt(bool *ok=0) const
Returns the variant as an unsigned int if the variant has type() UInt , Bool , ByteArray ...
Definition: qvariant.cpp:2644
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
Definition: qiodevice.cpp:752
virtual qint64 bytesAvailable() const
Reimplemented Function
const QObjectList & children() const
Returns a list of child objects.
Definition: qobject.h:197
virtual bool open(OpenMode mode)
Opens the device and sets its OpenMode to mode.
Definition: qiodevice.cpp:570
QObject * parent
Definition: qobject.h:92
virtual bool canReadLine() const
Returns true if a complete line of data can be read from the device; otherwise returns false...
Definition: qiodevice.cpp:1330
LocalSocketError
The LocalServerError enumeration represents the errors that can occur.
Definition: qlocalsocket.h:64
bool setSocketDescriptor(quintptr socketDescriptor, LocalSocketState socketState=ConnectedState, OpenMode openMode=ReadWrite)
void disconnectFromServer()
Attempts to close the socket.