summaryrefslogtreecommitdiffstats
path: root/src/network/socket
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/socket')
-rw-r--r--src/network/socket/qabstractsocket.cpp51
-rw-r--r--src/network/socket/qabstractsocket.h1
-rw-r--r--src/network/socket/qabstractsocket_p.h2
-rw-r--r--src/network/socket/qabstractsocketengine_p.h2
-rw-r--r--src/network/socket/qhttpsocketengine.cpp10
-rw-r--r--src/network/socket/qhttpsocketengine_p.h2
-rw-r--r--src/network/socket/qlocalserver_unix.cpp22
-rw-r--r--src/network/socket/qnativesocketengine.cpp6
-rw-r--r--src/network/socket/qnativesocketengine_p.h2
-rw-r--r--src/network/socket/qsocks5socketengine.cpp14
-rw-r--r--src/network/socket/qsocks5socketengine_p.h2
11 files changed, 89 insertions, 25 deletions
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 9fb0b47..89a6e91 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -462,6 +462,7 @@ QAbstractSocketPrivate::QAbstractSocketPrivate()
isBuffered(false),
blockingTimeout(30000),
connectTimer(0),
+ disconnectTimer(0),
connectTimeElapsed(0),
hostLookupId(-1),
socketType(QAbstractSocket::UnknownSocketType),
@@ -497,9 +498,10 @@ void QAbstractSocketPrivate::resetSocketLayer()
socketEngine = 0;
cachedSocketDescriptor = -1;
}
- if (connectTimer) {
+ if (connectTimer)
connectTimer->stop();
- }
+ if (disconnectTimer)
+ disconnectTimer->stop();
}
/*! \internal
@@ -669,11 +671,11 @@ bool QAbstractSocketPrivate::canWriteNotification()
if (socketEngine) {
#if defined (Q_OS_WIN)
- if (!writeBuffer.isEmpty())
- socketEngine->setWriteNotificationEnabled(true);
+ if (!writeBuffer.isEmpty())
+ socketEngine->setWriteNotificationEnabled(true);
#else
- if (writeBuffer.isEmpty())
- socketEngine->setWriteNotificationEnabled(false);
+ if (writeBuffer.isEmpty() && socketEngine->bytesToWrite() == 0)
+ socketEngine->setWriteNotificationEnabled(false);
#endif
}
@@ -710,11 +712,17 @@ void QAbstractSocketPrivate::connectionNotification()
bool QAbstractSocketPrivate::flush()
{
Q_Q(QAbstractSocket);
- if (!socketEngine || !socketEngine->isValid() || writeBuffer.isEmpty()) {
+ if (!socketEngine || !socketEngine->isValid() || (writeBuffer.isEmpty()
+ && socketEngine->bytesToWrite() == 0)) {
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::flush() nothing to do: valid ? %s, writeBuffer.isEmpty() ? %s",
socketEngine->isValid() ? "yes" : "no", writeBuffer.isEmpty() ? "yes" : "no");
#endif
+
+ // this covers the case when the buffer was empty, but we had to wait for the socket engine to finish
+ if (state == QAbstractSocket::ClosingState)
+ q->disconnectFromHost();
+
return false;
}
@@ -751,7 +759,8 @@ bool QAbstractSocketPrivate::flush()
}
}
- if (writeBuffer.isEmpty() && socketEngine && socketEngine->isWriteNotificationEnabled())
+ if (writeBuffer.isEmpty() && socketEngine && socketEngine->isWriteNotificationEnabled()
+ && !socketEngine->bytesToWrite())
socketEngine->setWriteNotificationEnabled(false);
if (state == QAbstractSocket::ClosingState)
q->disconnectFromHost();
@@ -1087,6 +1096,15 @@ void QAbstractSocketPrivate::_q_abortConnectionAttempt()
}
}
+void QAbstractSocketPrivate::_q_forceDisconnect()
+{
+ Q_Q(QAbstractSocket);
+ if (socketEngine && socketEngine->isValid() && state == QAbstractSocket::ClosingState) {
+ socketEngine->close();
+ q->disconnectFromHost();
+ }
+}
+
/*! \internal
Reads data from the socket layer into the read buffer. Returns
@@ -2347,7 +2365,22 @@ void QAbstractSocket::disconnectFromHostImplementation()
}
// Wait for pending data to be written.
- if (d->socketEngine && d->socketEngine->isValid() && d->writeBuffer.size() > 0) {
+ if (d->socketEngine && d->socketEngine->isValid() && (d->writeBuffer.size() > 0
+ || d->socketEngine->bytesToWrite() > 0)) {
+ // hack: when we are waiting for the socket engine to write bytes (only
+ // possible when using Socks5 or HTTP socket engine), then close
+ // anyway after 2 seconds. This is to prevent a timeout on Mac, where we
+ // sometimes just did not get the write notifier from the underlying
+ // CFSocket and no progress was made.
+ if (d->writeBuffer.size() == 0 && d->socketEngine->bytesToWrite() > 0) {
+ if (!d->disconnectTimer) {
+ d->disconnectTimer = new QTimer(this);
+ connect(d->disconnectTimer, SIGNAL(timeout()), this,
+ SLOT(_q_forceDisconnect()), Qt::DirectConnection);
+ }
+ if (!d->disconnectTimer->isActive())
+ d->disconnectTimer->start(2000);
+ }
d->socketEngine->setWriteNotificationEnabled(true);
#if defined(QABSTRACTSOCKET_DEBUG)
diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h
index 5d94a01..5cfae17 100644
--- a/src/network/socket/qabstractsocket.h
+++ b/src/network/socket/qabstractsocket.h
@@ -216,6 +216,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_startConnecting(const QHostInfo &))
Q_PRIVATE_SLOT(d_func(), void _q_abortConnectionAttempt())
Q_PRIVATE_SLOT(d_func(), void _q_testConnection())
+ Q_PRIVATE_SLOT(d_func(), void _q_forceDisconnect())
#ifdef QT3_SUPPORT
public:
diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h
index 8ccddd3..acf82bf 100644
--- a/src/network/socket/qabstractsocket_p.h
+++ b/src/network/socket/qabstractsocket_p.h
@@ -93,6 +93,7 @@ public:
void _q_startConnecting(const QHostInfo &hostInfo);
void _q_testConnection();
void _q_abortConnectionAttempt();
+ void _q_forceDisconnect();
bool readSocketNotifierCalled;
bool readSocketNotifierState;
@@ -148,6 +149,7 @@ public:
int blockingTimeout;
QTimer *connectTimer;
+ QTimer *disconnectTimer;
int connectTimeElapsed;
int hostLookupId;
diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h
index c639092..14b3c81 100644
--- a/src/network/socket/qabstractsocketengine_p.h
+++ b/src/network/socket/qabstractsocketengine_p.h
@@ -126,6 +126,8 @@ public:
virtual qint64 pendingDatagramSize() const = 0;
#endif
+ virtual qint64 bytesToWrite() const = 0;
+
virtual int option(SocketOption option) const = 0;
virtual bool setOption(SocketOption option, int value) = 0;
diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp
index fb61dbf..5c28318 100644
--- a/src/network/socket/qhttpsocketengine.cpp
+++ b/src/network/socket/qhttpsocketengine.cpp
@@ -276,6 +276,16 @@ qint64 QHttpSocketEngine::pendingDatagramSize() const
}
#endif // QT_NO_UDPSOCKET
+qint64 QHttpSocketEngine::bytesToWrite() const
+{
+ Q_D(const QHttpSocketEngine);
+ if (d->socket) {
+ return d->socket->bytesToWrite();
+ } else {
+ return 0;
+ }
+}
+
int QHttpSocketEngine::option(SocketOption option) const
{
Q_D(const QHttpSocketEngine);
diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h
index a423116..76430db 100644
--- a/src/network/socket/qhttpsocketengine_p.h
+++ b/src/network/socket/qhttpsocketengine_p.h
@@ -110,6 +110,8 @@ public:
qint64 pendingDatagramSize() const;
#endif // QT_NO_UDPSOCKET
+ qint64 bytesToWrite() const;
+
int option(SocketOption option) const;
bool setOption(SocketOption option, int value);
diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp
index 5ffe0c0..e09e547 100644
--- a/src/network/socket/qlocalserver_unix.cpp
+++ b/src/network/socket/qlocalserver_unix.cpp
@@ -216,24 +216,14 @@ void QLocalServerPrivate::waitForNewConnection(int msec, bool *timedOut)
timeout.tv_sec = msec / 1000;
timeout.tv_usec = (msec % 1000) * 1000;
- // timeout can not be 0 or else select will return an error.
- if (0 == msec)
- timeout.tv_usec = 1000;
-
int result = -1;
- // on Linux timeout will be updated by select, but _not_ on other systems.
- QTime timer;
- timer.start();
- while (pendingConnections.isEmpty() && (-1 == msec || timer.elapsed() < msec)) {
- result = ::select(listenSocket + 1, &readfds, 0, 0, &timeout);
- if (-1 == result && errno != EINTR) {
- setError(QLatin1String("QLocalServer::waitForNewConnection"));
- closeServer();
- break;
- }
- if (result > 0)
- _q_onNewConnection();
+ result = qt_safe_select(listenSocket + 1, &readfds, 0, 0, (msec == -1) ? 0 : &timeout);
+ if (-1 == result) {
+ setError(QLatin1String("QLocalServer::waitForNewConnection"));
+ closeServer();
}
+ if (result > 0)
+ _q_onNewConnection();
if (timedOut)
*timedOut = (result == 0);
}
diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp
index 8de821b..ecf5ad9 100644
--- a/src/network/socket/qnativesocketengine.cpp
+++ b/src/network/socket/qnativesocketengine.cpp
@@ -754,6 +754,12 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 size)
return d->nativeWrite(data, size);
}
+
+qint64 QNativeSocketEngine::bytesToWrite() const
+{
+ return 0;
+}
+
/*!
Reads up to \a maxSize bytes into \a data from the socket.
Returns the number of bytes read, or -1 if an error occurred.
diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index 1f6a243..a03d8f1 100644
--- a/src/network/socket/qnativesocketengine_p.h
+++ b/src/network/socket/qnativesocketengine_p.h
@@ -135,6 +135,8 @@ public:
bool hasPendingDatagrams() const;
qint64 pendingDatagramSize() const;
+ qint64 bytesToWrite() const;
+
qint64 receiveBufferSize() const;
void setReceiveBufferSize(qint64 bufferSize);
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index 30074cf..bd60ad1 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -1235,6 +1235,9 @@ void QSocks5SocketEnginePrivate::_q_controlSocketError(QAbstractSocket::SocketEr
if (!readNotificationPending)
connectData->readBuffer.clear();
emitReadNotification();
+ data->controlSocket->close();
+ // cause a disconnect in the outer socket
+ emitWriteNotification();
} else if (socks5State == Uninitialized
|| socks5State == AuthenticationMethodsSent
|| socks5State == Authenticating
@@ -1245,6 +1248,7 @@ void QSocks5SocketEnginePrivate::_q_controlSocketError(QAbstractSocket::SocketEr
} else {
q_func()->setError(data->controlSocket->error(), data->controlSocket->errorString());
emitReadNotification();
+ emitWriteNotification();
}
}
@@ -1623,6 +1627,16 @@ qint64 QSocks5SocketEngine::pendingDatagramSize() const
}
#endif // QT_NO_UDPSOCKET
+qint64 QSocks5SocketEngine::bytesToWrite() const
+{
+ Q_D(const QSocks5SocketEngine);
+ if (d->data && d->data->controlSocket) {
+ return d->data->controlSocket->bytesToWrite();
+ } else {
+ return 0;
+ }
+}
+
int QSocks5SocketEngine::option(SocketOption option) const
{
Q_D(const QSocks5SocketEngine);
diff --git a/src/network/socket/qsocks5socketengine_p.h b/src/network/socket/qsocks5socketengine_p.h
index 7cb0920..2402517 100644
--- a/src/network/socket/qsocks5socketengine_p.h
+++ b/src/network/socket/qsocks5socketengine_p.h
@@ -100,6 +100,8 @@ public:
qint64 pendingDatagramSize() const;
#endif // QT_NO_UDPSOCKET
+ qint64 bytesToWrite() const;
+
int option(SocketOption option) const;
bool setOption(SocketOption option, int value);