winrt: Move handling of new socket connections into worker

Same as with receiving data, the "newConnection callback" might be
triggered late and cause a crash if it accesses data of a destroyed
object. By moving the handling of this callback to a worker without
much logic we can prevent these late callbacks from doing any harm.
The signals are no longer connected and thus do not trigger any
problems.

Change-Id: Ic61584f12a46506abe12d7b21403d0c0970c0aae
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
bb10
Oliver Wolff 2017-05-09 13:58:34 +02:00
parent 96120d7587
commit 7076438db4
2 changed files with 166 additions and 151 deletions

View File

@ -194,9 +194,22 @@ public:
Q_ASSERT_SUCCEEDED(hr);
}
}
if (connectOp) {
ComPtr<IAsyncInfo> info;
HRESULT hr = connectOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
if (info) {
hr = info->Cancel();
Q_ASSERT_SUCCEEDED(hr);
hr = info->Close();
Q_ASSERT_SUCCEEDED(hr);
}
}
}
signals:
void connectOpFinished(bool success, QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString);
void newDatagramsReceived(const QList<WinRtDatagram> &datagram);
void newDataReceived(const QVector<QByteArray> &data);
void socketErrorOccured(QAbstractSocket::SocketError error);
@ -234,6 +247,45 @@ public:
Q_ASSERT_SUCCEEDED(hr);
}
HRESULT onConnectOpFinished(IAsyncAction *action, AsyncStatus)
{
HRESULT hr = action->GetResults();
if (FAILED(hr)) {
switch (hr) {
case HRESULT_FROM_WIN32(WSAETIMEDOUT):
emit connectOpFinished(false, QAbstractSocket::NetworkError, WinRTSocketEngine::ConnectionTimeOutErrorString);
return S_OK;
case HRESULT_FROM_WIN32(WSAEHOSTUNREACH):
emit connectOpFinished(false, QAbstractSocket::HostNotFoundError, WinRTSocketEngine::HostUnreachableErrorString);
return S_OK;
case HRESULT_FROM_WIN32(WSAECONNREFUSED):
emit connectOpFinished(false, QAbstractSocket::ConnectionRefusedError, WinRTSocketEngine::ConnectionRefusedErrorString);
return S_OK;
default:
emit connectOpFinished(false, QAbstractSocket::UnknownSocketError, WinRTSocketEngine::UnknownSocketErrorString);
return S_OK;
}
}
// The callback might be triggered several times if we do not cancel/reset it here
if (connectOp) {
ComPtr<IAsyncInfo> info;
hr = connectOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
if (info) {
hr = info->Cancel();
Q_ASSERT_SUCCEEDED(hr);
hr = info->Close();
Q_ASSERT_SUCCEEDED(hr);
}
hr = connectOp.Reset();
Q_ASSERT_SUCCEEDED(hr);
}
emit connectOpFinished(true, QAbstractSocket::UnknownSocketError, WinRTSocketEngine::UnknownSocketErrorString);
return S_OK;
}
HRESULT OnNewDatagramReceived(IDatagramSocket *, IDatagramSocketMessageReceivedEventArgs *args)
{
WinRtDatagram datagram;
@ -378,6 +430,7 @@ public:
void setTcpSocket(ComPtr<IStreamSocket> socket) { tcpSocket = socket; }
private:
friend class QNativeSocketEngine;
ComPtr<IStreamSocket> tcpSocket;
QList<WinRtDatagram> pendingDatagrams;
@ -386,6 +439,7 @@ private:
// Protects pendingData/pendingDatagrams which are accessed from native callbacks
QMutex mutex;
ComPtr<IAsyncAction> connectOp;
ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> initialReadOp;
ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> readOp;
@ -481,6 +535,7 @@ QNativeSocketEngine::QNativeSocketEngine(QObject *parent)
: QAbstractSocketEngine(*new QNativeSocketEnginePrivate(), parent)
{
qRegisterMetaType<WinRtDatagram>();
qRegisterMetaType<WinRTSocketEngine::ErrorString>();
#ifndef QT_NO_SSL
Q_D(QNativeSocketEngine);
if (parent)
@ -490,6 +545,8 @@ QNativeSocketEngine::QNativeSocketEngine(QObject *parent)
connect(this, SIGNAL(connectionReady()), SLOT(connectionNotification()), Qt::QueuedConnection);
connect(this, SIGNAL(readReady()), SLOT(readNotification()), Qt::QueuedConnection);
connect(this, SIGNAL(writeReady()), SLOT(writeNotification()), Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::connectOpFinished,
this, &QNativeSocketEngine::handleConnectOpFinished, Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::newDatagramsReceived, this, &QNativeSocketEngine::handleNewDatagrams, Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::newDataReceived,
this, &QNativeSocketEngine::handleNewData, Qt::QueuedConnection);
@ -531,7 +588,7 @@ bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket::
if (!d->socketDescriptor || !d->fetchConnectionParameters()) {
d->setError(QAbstractSocket::UnsupportedSocketOperationError,
d->InvalidSocketErrorString);
WinRTSocketEngine::InvalidSocketErrorString);
d->socketDescriptor = -1;
return false;
}
@ -599,9 +656,9 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
const QString portString = QString::number(port);
HStringReference portReference(reinterpret_cast<LPCWSTR>(portString.utf16()));
if (d->socketType == QAbstractSocket::TcpSocket)
hr = d->tcpSocket()->ConnectAsync(remoteHost.Get(), portReference.Get(), &d->connectOp);
hr = d->tcpSocket()->ConnectAsync(remoteHost.Get(), portReference.Get(), &d->worker->connectOp);
else if (d->socketType == QAbstractSocket::UdpSocket)
hr = d->udpSocket()->ConnectAsync(remoteHost.Get(), portReference.Get(), &d->connectOp);
hr = d->udpSocket()->ConnectAsync(remoteHost.Get(), portReference.Get(), &d->worker->connectOp);
if (hr == E_ACCESSDENIED) {
qErrnoWarning(hr, "QNativeSocketEngine::connectToHostByName: Unable to connect to host (%s:%hu/%s). "
"Please check your manifest capabilities.",
@ -622,8 +679,8 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
d->socketState = QAbstractSocket::ConnectingState;
QEventDispatcherWinRT::runOnXamlThread([d, &hr]() {
hr = d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
d, &QNativeSocketEnginePrivate::handleConnectOpFinished).Get());
hr = d->worker->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
d->worker, &SocketEngineWorker::onConnectOpFinished).Get());
RETURN_OK_IF_FAILED("connectToHostByName: Could not register \"connectOp\" callback");
return S_OK;
});
@ -677,7 +734,7 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
qErrnoWarning(hr, "Unable to bind socket (%s:%hu/%s). Please check your manifest capabilities.",
qPrintable(address.toString()), port, socketDescription(this).constData());
d->setError(QAbstractSocket::SocketAccessError,
QNativeSocketEnginePrivate::AccessErrorString);
WinRTSocketEngine::AccessErrorString);
d->socketState = QAbstractSocket::UnconnectedState;
specificErrorSet = true;
return S_OK;
@ -687,14 +744,14 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
hr = QWinRTFunctions::await(op);
if (hr == 0x80072741) { // The requested address is not valid in its context
d->setError(QAbstractSocket::SocketAddressNotAvailableError,
QNativeSocketEnginePrivate::AddressNotAvailableErrorString);
WinRTSocketEngine::AddressNotAvailableErrorString);
d->socketState = QAbstractSocket::UnconnectedState;
specificErrorSet = true;
return S_OK;
// Only one usage of each socket address (protocol/network address/port) is normally permitted
} else if (hr == 0x80072740) {
d->setError(QAbstractSocket::AddressInUseError,
QNativeSocketEnginePrivate::AddressInuseErrorString);
WinRTSocketEngine::AddressInuseErrorString);
d->socketState = QAbstractSocket::UnconnectedState;
specificErrorSet = true;
return S_OK;
@ -705,7 +762,7 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
if (FAILED(hr)) {
if (!specificErrorSet) {
d->setError(QAbstractSocket::UnknownSocketError,
QNativeSocketEnginePrivate::UnknownSocketErrorString);
WinRTSocketEngine::UnknownSocketErrorString);
d->socketState = QAbstractSocket::UnconnectedState;
}
return false;
@ -737,7 +794,7 @@ int QNativeSocketEngine::accept()
Q_CHECK_TYPE(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket, -1);
if (d->socketDescriptor == -1 || d->pendingConnections.isEmpty()) {
d->setError(QAbstractSocket::TemporaryError, QNativeSocketEnginePrivate::TemporaryErrorString);
d->setError(QAbstractSocket::TemporaryError, WinRTSocketEngine::TemporaryErrorString);
return -1;
}
@ -767,18 +824,6 @@ void QNativeSocketEngine::close()
d->notifyOnException = false;
HRESULT hr;
if (d->connectOp) {
ComPtr<IAsyncInfo> info;
hr = d->connectOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
if (info) {
hr = info->Cancel();
Q_ASSERT_SUCCEEDED(hr);
hr = info->Close();
Q_ASSERT_SUCCEEDED(hr);
}
}
if (d->socketType == QAbstractSocket::TcpSocket) {
hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
HRESULT hr;
@ -924,7 +969,7 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 len)
qint64 bytesWritten = writeIOStream(stream, data, len);
if (bytesWritten < 0)
d->setError(QAbstractSocket::SocketAccessError, QNativeSocketEnginePrivate::AccessErrorString);
d->setError(QAbstractSocket::SocketAccessError, WinRTSocketEngine::AccessErrorString);
else if (bytesWritten > 0 && d->notifyOnWrite)
emit writeReady();
@ -1089,7 +1134,7 @@ bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
}
d->setError(QAbstractSocket::SocketTimeoutError,
QNativeSocketEnginePrivate::TimeOutErrorString);
WinRTSocketEngine::TimeOutErrorString);
if (timedOut)
*timedOut = true;
@ -1102,9 +1147,9 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut)
Q_UNUSED(timedOut);
Q_D(QNativeSocketEngine);
if (d->socketState == QAbstractSocket::ConnectingState) {
HRESULT hr = QWinRTFunctions::await(d->connectOp, QWinRTFunctions::ProcessMainThreadEvents);
HRESULT hr = QWinRTFunctions::await(d->worker->connectOp, QWinRTFunctions::ProcessMainThreadEvents);
if (SUCCEEDED(hr)) {
d->handleConnectOpFinished(d->connectOp.Get(), Completed);
handleConnectOpFinished(true, QAbstractSocket::UnknownSocketError, WinRTSocketEngine::UnknownSocketErrorString);
return true;
}
}
@ -1176,6 +1221,32 @@ void QNativeSocketEngine::establishRead()
Q_ASSERT_SUCCEEDED(hr);
}
void QNativeSocketEngine::handleConnectOpFinished(bool success, QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString)
{
Q_D(QNativeSocketEngine);
disconnect(d->worker, &SocketEngineWorker::connectOpFinished,
this, &QNativeSocketEngine::handleConnectOpFinished);
if (!success) {
d->setError(error, errorString);
d->socketState = QAbstractSocket::UnconnectedState;
return;
}
d->socketState = QAbstractSocket::ConnectedState;
emit connectionReady();
if (d->socketType != QAbstractSocket::TcpSocket)
return;
#ifndef QT_NO_SSL
// Delay the reader so that the SSL socket can upgrade
if (d->sslSocket)
QObject::connect(qobject_cast<QSslSocket *>(d->sslSocket), &QSslSocket::encrypted, this, &QNativeSocketEngine::establishRead);
else
#endif
establishRead();
}
void QNativeSocketEngine::handleNewDatagrams(const QList<WinRtDatagram> &datagrams)
{
Q_D(QNativeSocketEngine);
@ -1198,13 +1269,13 @@ void QNativeSocketEngine::handleNewData(const QVector<QByteArray> &data)
void QNativeSocketEngine::handleTcpError(QAbstractSocket::SocketError error)
{
Q_D(QNativeSocketEngine);
QNativeSocketEnginePrivate::ErrorString errorString;
WinRTSocketEngine::ErrorString errorString;
switch (error) {
case QAbstractSocket::RemoteHostClosedError:
errorString = QNativeSocketEnginePrivate::RemoteHostClosedErrorString;
errorString = WinRTSocketEngine::RemoteHostClosedErrorString;
break;
default:
errorString = QNativeSocketEnginePrivate::UnknownSocketErrorString;
errorString = WinRTSocketEngine::UnknownSocketErrorString;
}
d->setError(error, errorString);
@ -1271,7 +1342,7 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
// Make the socket nonblocking.
if (!setOption(QAbstractSocketEngine::NonBlockingSocketOption, 1)) {
setError(QAbstractSocket::UnsupportedSocketOperationError, NonBlockingInitFailedErrorString);
setError(QAbstractSocket::UnsupportedSocketOperationError, WinRTSocketEngine::NonBlockingInitFailedErrorString);
q_func()->close();
return false;
}
@ -1307,7 +1378,7 @@ QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate()
worker->deleteLater();
}
void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, ErrorString errorString) const
void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString) const
{
if (hasSetSocketError) {
// Only set socket errors once for one engine; expect the
@ -1325,86 +1396,86 @@ void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, Er
socketError = error;
switch (errorString) {
case NonBlockingInitFailedErrorString:
case WinRTSocketEngine::NonBlockingInitFailedErrorString:
socketErrorString = QNativeSocketEngine::tr("Unable to initialize non-blocking socket");
break;
case BroadcastingInitFailedErrorString:
case WinRTSocketEngine::BroadcastingInitFailedErrorString:
socketErrorString = QNativeSocketEngine::tr("Unable to initialize broadcast socket");
break;
// should not happen anymore
case NoIpV6ErrorString:
case WinRTSocketEngine::NoIpV6ErrorString:
socketErrorString = QNativeSocketEngine::tr("Attempt to use IPv6 socket on a platform with no IPv6 support");
break;
case RemoteHostClosedErrorString:
case WinRTSocketEngine::RemoteHostClosedErrorString:
socketErrorString = QNativeSocketEngine::tr("The remote host closed the connection");
break;
case TimeOutErrorString:
case WinRTSocketEngine::TimeOutErrorString:
socketErrorString = QNativeSocketEngine::tr("Network operation timed out");
break;
case ResourceErrorString:
case WinRTSocketEngine::ResourceErrorString:
socketErrorString = QNativeSocketEngine::tr("Out of resources");
break;
case OperationUnsupportedErrorString:
case WinRTSocketEngine::OperationUnsupportedErrorString:
socketErrorString = QNativeSocketEngine::tr("Unsupported socket operation");
break;
case ProtocolUnsupportedErrorString:
case WinRTSocketEngine::ProtocolUnsupportedErrorString:
socketErrorString = QNativeSocketEngine::tr("Protocol type not supported");
break;
case InvalidSocketErrorString:
case WinRTSocketEngine::InvalidSocketErrorString:
socketErrorString = QNativeSocketEngine::tr("Invalid socket descriptor");
break;
case HostUnreachableErrorString:
case WinRTSocketEngine::HostUnreachableErrorString:
socketErrorString = QNativeSocketEngine::tr("Host unreachable");
break;
case NetworkUnreachableErrorString:
case WinRTSocketEngine::NetworkUnreachableErrorString:
socketErrorString = QNativeSocketEngine::tr("Network unreachable");
break;
case AccessErrorString:
case WinRTSocketEngine::AccessErrorString:
socketErrorString = QNativeSocketEngine::tr("Permission denied");
break;
case ConnectionTimeOutErrorString:
case WinRTSocketEngine::ConnectionTimeOutErrorString:
socketErrorString = QNativeSocketEngine::tr("Connection timed out");
break;
case ConnectionRefusedErrorString:
case WinRTSocketEngine::ConnectionRefusedErrorString:
socketErrorString = QNativeSocketEngine::tr("Connection refused");
break;
case AddressInuseErrorString:
case WinRTSocketEngine::AddressInuseErrorString:
socketErrorString = QNativeSocketEngine::tr("The bound address is already in use");
break;
case AddressNotAvailableErrorString:
case WinRTSocketEngine::AddressNotAvailableErrorString:
socketErrorString = QNativeSocketEngine::tr("The address is not available");
break;
case AddressProtectedErrorString:
case WinRTSocketEngine::AddressProtectedErrorString:
socketErrorString = QNativeSocketEngine::tr("The address is protected");
break;
case DatagramTooLargeErrorString:
case WinRTSocketEngine::DatagramTooLargeErrorString:
socketErrorString = QNativeSocketEngine::tr("Datagram was too large to send");
break;
case SendDatagramErrorString:
case WinRTSocketEngine::SendDatagramErrorString:
socketErrorString = QNativeSocketEngine::tr("Unable to send a message");
break;
case ReceiveDatagramErrorString:
case WinRTSocketEngine::ReceiveDatagramErrorString:
socketErrorString = QNativeSocketEngine::tr("Unable to receive a message");
break;
case WriteErrorString:
case WinRTSocketEngine::WriteErrorString:
socketErrorString = QNativeSocketEngine::tr("Unable to write");
break;
case ReadErrorString:
case WinRTSocketEngine::ReadErrorString:
socketErrorString = QNativeSocketEngine::tr("Network error");
break;
case PortInuseErrorString:
case WinRTSocketEngine::PortInuseErrorString:
socketErrorString = QNativeSocketEngine::tr("Another socket is already listening on the same port");
break;
case NotSocketErrorString:
case WinRTSocketEngine::NotSocketErrorString:
socketErrorString = QNativeSocketEngine::tr("Operation on non-socket");
break;
case InvalidProxyTypeString:
case WinRTSocketEngine::InvalidProxyTypeString:
socketErrorString = QNativeSocketEngine::tr("The proxy type is invalid for this operation");
break;
case TemporaryErrorString:
case WinRTSocketEngine::TemporaryErrorString:
socketErrorString = QNativeSocketEngine::tr("Temporary error");
break;
case UnknownSocketErrorString:
case WinRTSocketEngine::UnknownSocketErrorString:
socketErrorString = QNativeSocketEngine::tr("Unknown error");
break;
}
@ -1615,65 +1686,6 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener
return S_OK;
}
HRESULT QNativeSocketEnginePrivate::handleConnectOpFinished(IAsyncAction *action, AsyncStatus)
{
Q_Q(QNativeSocketEngine);
if (wasDeleted || !connectOp) // Protect against a late callback
return S_OK;
HRESULT hr = action->GetResults();
switch (hr) {
case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
socketState = QAbstractSocket::UnconnectedState;
return S_OK;
case 0x80072751: // A socket operation was attempted to an unreachable host.
setError(QAbstractSocket::HostNotFoundError, HostUnreachableErrorString);
socketState = QAbstractSocket::UnconnectedState;
return S_OK;
case 0x8007274d: // No connection could be made because the target machine actively refused it.
setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
socketState = QAbstractSocket::UnconnectedState;
return S_OK;
default:
if (FAILED(hr)) {
setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
socketState = QAbstractSocket::UnconnectedState;
return S_OK;
}
}
// The callback might be triggered several times if we do not cancel/reset it here
if (connectOp) {
ComPtr<IAsyncInfo> info;
hr = connectOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
if (info) {
hr = info->Cancel();
Q_ASSERT_SUCCEEDED(hr);
hr = info->Close();
Q_ASSERT_SUCCEEDED(hr);
}
hr = connectOp.Reset();
Q_ASSERT_SUCCEEDED(hr);
}
socketState = QAbstractSocket::ConnectedState;
emit q->connectionReady();
if (socketType != QAbstractSocket::TcpSocket)
return S_OK;
#ifndef QT_NO_SSL
// Delay the reader so that the SSL socket can upgrade
if (sslSocket)
QObject::connect(qobject_cast<QSslSocket *>(sslSocket), &QSslSocket::encrypted, q, &QNativeSocketEngine::establishRead);
else
#endif
q->establishRead();
return S_OK;
}
HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args)
{
Q_Q(QNativeSocketEngine);

View File

@ -63,6 +63,39 @@
QT_BEGIN_NAMESPACE
namespace WinRTSocketEngine {
enum ErrorString {
NonBlockingInitFailedErrorString,
BroadcastingInitFailedErrorString,
NoIpV6ErrorString,
RemoteHostClosedErrorString,
TimeOutErrorString,
ResourceErrorString,
OperationUnsupportedErrorString,
ProtocolUnsupportedErrorString,
InvalidSocketErrorString,
HostUnreachableErrorString,
NetworkUnreachableErrorString,
AccessErrorString,
ConnectionTimeOutErrorString,
ConnectionRefusedErrorString,
AddressInuseErrorString,
AddressNotAvailableErrorString,
AddressProtectedErrorString,
DatagramTooLargeErrorString,
SendDatagramErrorString,
ReceiveDatagramErrorString,
WriteErrorString,
ReadErrorString,
PortInuseErrorString,
NotSocketErrorString,
InvalidProxyTypeString,
TemporaryErrorString,
UnknownSocketErrorString = -1
};
}
class QNativeSocketEnginePrivate;
class SocketEngineWorker;
@ -143,6 +176,8 @@ signals:
private slots:
void establishRead();
void handleConnectOpFinished(bool success, QAbstractSocket::SocketError error,
WinRTSocketEngine::ErrorString errorString);
void handleNewDatagrams(const QList<WinRtDatagram> &datagram);
void handleNewData(const QVector<QByteArray> &data);
void handleTcpError(QAbstractSocket::SocketError error);
@ -168,38 +203,7 @@ public:
bool notifyOnRead, notifyOnWrite, notifyOnException;
QAtomicInt closingDown;
enum ErrorString {
NonBlockingInitFailedErrorString,
BroadcastingInitFailedErrorString,
NoIpV6ErrorString,
RemoteHostClosedErrorString,
TimeOutErrorString,
ResourceErrorString,
OperationUnsupportedErrorString,
ProtocolUnsupportedErrorString,
InvalidSocketErrorString,
HostUnreachableErrorString,
NetworkUnreachableErrorString,
AccessErrorString,
ConnectionTimeOutErrorString,
ConnectionRefusedErrorString,
AddressInuseErrorString,
AddressNotAvailableErrorString,
AddressProtectedErrorString,
DatagramTooLargeErrorString,
SendDatagramErrorString,
ReceiveDatagramErrorString,
WriteErrorString,
ReadErrorString,
PortInuseErrorString,
NotSocketErrorString,
InvalidProxyTypeString,
TemporaryErrorString,
UnknownSocketErrorString = -1
};
void setError(QAbstractSocket::SocketError error, ErrorString errorString) const;
void setError(QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString) const;
// native functions
int option(QNativeSocketEngine::SocketOption option) const;
@ -216,7 +220,6 @@ private:
inline ABI::Windows::Networking::Sockets::IDatagramSocket *udpSocket() const
{ return reinterpret_cast<ABI::Windows::Networking::Sockets::IDatagramSocket *>(socketDescriptor); }
Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocketListener> tcpListener;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> connectOp;
// In case of TCP readMutex protects readBytes and bytesAvailable. In case of UDP it is
// pendingDatagrams. They are written inside native callbacks (handleReadyRead and
@ -242,11 +245,11 @@ private:
ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args);
HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener,
ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args);
HRESULT handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
};
QT_END_NAMESPACE
Q_DECLARE_METATYPE(WinRtDatagram)
Q_DECLARE_METATYPE(WinRTSocketEngine::ErrorString)
#endif // QNATIVESOCKETENGINE_WINRT_P_H