summaryrefslogtreecommitdiffstats
path: root/src/network/socket
diff options
context:
space:
mode:
authorAndrew Knight <andrew.knight@digia.com>2014-08-26 23:29:31 +0300
committerAndrew Knight <andrew.knight@digia.com>2014-08-28 05:59:15 +0200
commitda72e1b0e8fce7c221d5aaafe336f01e68d9f97a (patch)
treefc1386afb8257c9b48b2aabf4ec838c28bf095ee /src/network/socket
parentdd305aee786a03455b6f86b3d342fc30673a0fd4 (diff)
winrt: Refactor internal socket buffer
Simplify the temporary buffer usage by using the built-in WinRT Buffer class. This also allows one use of the local event loop to be removed. Change-Id: Ice552910227ffbe31c6e8716ff7896af7c4532ef Reviewed-by: Maurice Kalinowski <maurice.kalinowski@digia.com>
Diffstat (limited to 'src/network/socket')
-rw-r--r--src/network/socket/qnativesocketengine_winrt.cpp189
-rw-r--r--src/network/socket/qnativesocketengine_winrt_p.h2
2 files changed, 70 insertions, 121 deletions
diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp
index d0e4a99b39..2ea6d6e015 100644
--- a/src/network/socket/qnativesocketengine_winrt.cpp
+++ b/src/network/socket/qnativesocketengine_winrt.cpp
@@ -130,6 +130,20 @@ struct SocketHandler
Q_GLOBAL_STATIC(SocketHandler, gSocketHandler)
+struct SocketGlobal
+{
+ SocketGlobal()
+ {
+ HRESULT hr;
+ hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
+ &bufferFactory);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ ComPtr<IBufferFactory> bufferFactory;
+};
+Q_GLOBAL_STATIC(SocketGlobal, g)
+
static inline QString qt_QStringFromHString(const HString &string)
{
UINT32 length;
@@ -137,60 +151,7 @@ static inline QString qt_QStringFromHString(const HString &string)
return QString::fromWCharArray(rawString, length);
}
-#define READ_BUFFER_SIZE 8192
-
-class ByteArrayBuffer : public Microsoft::WRL::RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>,
- IBuffer, Windows::Storage::Streams::IBufferByteAccess>
-{
-public:
- ByteArrayBuffer(int size) : m_bytes(size, Qt::Uninitialized), m_length(0)
- {
- }
-
- ByteArrayBuffer(const char *data, int size) : m_bytes(data, size), m_length(size)
- {
- }
-
- HRESULT __stdcall Buffer(byte **value)
- {
- *value = reinterpret_cast<byte *>(m_bytes.data());
- return S_OK;
- }
-
- HRESULT __stdcall get_Capacity(UINT32 *value)
- {
- *value = m_bytes.size();
- return S_OK;
- }
-
- HRESULT __stdcall get_Length(UINT32 *value)
- {
- *value = m_length;
- return S_OK;
- }
-
- HRESULT __stdcall put_Length(UINT32 value)
- {
- Q_ASSERT(value <= UINT32(m_bytes.size()));
- m_length = value;
- return S_OK;
- }
-
- ComPtr<IInputStream> inputStream() const
- {
- return m_stream;
- }
-
- void setInputStream(const ComPtr<IInputStream> &stream)
- {
- m_stream = stream;
- }
-
-private:
- QByteArray m_bytes;
- UINT32 m_length;
- ComPtr<IInputStream> m_stream;
-};
+#define READ_BUFFER_SIZE 65536
template <typename T>
static AsyncStatus opStatus(const ComPtr<T> &op)
@@ -414,13 +375,16 @@ int QNativeSocketEngine::accept()
if (d->socketType == QAbstractSocket::TcpSocket) {
IStreamSocket *socket = d->pendingConnections.takeFirst();
- IInputStream *stream;
- socket->get_InputStream(&stream);
- // TODO: delete buffer and stream on socket close
- ByteArrayBuffer *buffer = static_cast<ByteArrayBuffer *>(d->readBuffer.Get());
- buffer->setInputStream(stream);
+ HRESULT hr;
+ ComPtr<IBuffer> buffer;
+ hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<IInputStream> stream;
+ hr = socket->get_InputStream(&stream);
+ Q_ASSERT_SUCCEEDED(hr);
ComPtr<IAsyncBufferOperation> op;
- HRESULT hr = stream->ReadAsync(buffer, READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
+ hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
if (FAILED(hr)) {
qErrnoWarning(hr, "Faild to read from the socket buffer.");
return -1;
@@ -543,31 +507,26 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 len)
return -1;
}
- ComPtr<ByteArrayBuffer> buffer = Make<ByteArrayBuffer>(data, len);
+ ComPtr<IBuffer> buffer;
+ hr = g->bufferFactory->Create(len, &buffer);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = buffer->put_Length(len);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
+ hr = buffer.As(&byteArrayAccess);
+ Q_ASSERT_SUCCEEDED(hr);
+ byte *bytes;
+ hr = byteArrayAccess->Buffer(&bytes);
+ Q_ASSERT_SUCCEEDED(hr);
+ memcpy(bytes, data, len);
ComPtr<IAsyncOperationWithProgress<UINT32, UINT32>> op;
hr = stream->WriteAsync(buffer.Get(), &op);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to write to socket.");
- return -1;
- }
- hr = op->put_Completed(Callback<IAsyncOperationWithProgressCompletedHandler<UINT32, UINT32>>(
- d, &QNativeSocketEnginePrivate::handleWriteCompleted).Get());
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to set socket write callback.");
- return -1;
- }
-
- while (opStatus(op) == Started)
- d->eventLoop.processEvents();
-
- AsyncStatus status = opStatus(op);
- if (status == Error || status == Canceled)
- return -1;
+ RETURN_IF_FAILED("Failed to write to stream", return -1);
UINT32 bytesWritten;
- hr = op->GetResults(&bytesWritten);
+ hr = QWinRTFunctions::await(op, &bytesWritten);
if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get written socket length.");
+ d->setError(QAbstractSocket::SocketAccessError, QNativeSocketEnginePrivate::AccessErrorString);
return -1;
}
@@ -816,10 +775,13 @@ void QNativeSocketEngine::establishRead()
ComPtr<IInputStream> stream;
hr = d->tcpSocket()->get_InputStream(&stream);
RETURN_VOID_IF_FAILED("Failed to get socket input stream");
- ByteArrayBuffer *buffer = static_cast<ByteArrayBuffer *>(d->readBuffer.Get());
- buffer->setInputStream(stream);
+
+ ComPtr<IBuffer> buffer;
+ hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer);
+ Q_ASSERT_SUCCEEDED(hr);
+
ComPtr<IAsyncBufferOperation> op;
- hr = stream->ReadAsync(buffer, READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
+ hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
RETURN_VOID_IF_FAILED("Failed to initiate socket read");
hr = op->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
Q_ASSERT_SUCCEEDED(hr);
@@ -866,8 +828,6 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate()
, closingDown(false)
, socketDescriptor(-1)
{
- ComPtr<ByteArrayBuffer> buffer = Make<ByteArrayBuffer>(READ_BUFFER_SIZE);
- readBuffer = buffer;
}
QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate()
@@ -1222,22 +1182,25 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
if (status == Error || status == Canceled)
return S_OK;
- ByteArrayBuffer *buffer = 0;
- HRESULT hr = asyncInfo->GetResults((IBuffer **)&buffer);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get ready read results.");
- return S_OK;
- }
- UINT32 len;
- buffer->get_Length(&len);
- if (!len) {
+ ComPtr<IBuffer> buffer;
+ HRESULT hr = asyncInfo->GetResults(&buffer);
+ RETURN_OK_IF_FAILED("Failed to get read results buffer");
+
+ UINT32 bufferLength;
+ hr = buffer->get_Length(&bufferLength);
+ Q_ASSERT_SUCCEEDED(hr);
+ if (!bufferLength) {
if (q->isReadNotificationEnabled())
emit q->readReady();
return S_OK;
}
+ ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
+ hr = buffer.As(&byteArrayAccess);
+ Q_ASSERT_SUCCEEDED(hr);
byte *data;
- buffer->Buffer(&data);
+ hr = byteArrayAccess->Buffer(&data);
+ Q_ASSERT_SUCCEEDED(hr);
readMutex.lock();
if (readBytes.atEnd()) // Everything has been read; the buffer is safe to reset
@@ -1247,15 +1210,25 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
qint64 readPos = readBytes.pos();
readBytes.seek(readBytes.size());
Q_ASSERT(readBytes.atEnd());
- readBytes.write(reinterpret_cast<const char*>(data), qint64(len));
+ readBytes.write(reinterpret_cast<const char*>(data), qint64(bufferLength));
readBytes.seek(readPos);
readMutex.unlock();
if (q->isReadNotificationEnabled())
emit q->readReady();
+ ComPtr<IInputStream> stream;
+ hr = tcpSocket()->get_InputStream(&stream);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ // Reuse the stream buffer
+ hr = buffer->get_Capacity(&bufferLength);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = buffer->put_Length(0);
+ Q_ASSERT_SUCCEEDED(hr);
+
ComPtr<IAsyncBufferOperation> op;
- hr = buffer->inputStream()->ReadAsync(buffer, READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
+ hr = stream->ReadAsync(buffer.Get(), bufferLength, InputStreamOptions_Partial, &op);
if (FAILED(hr)) {
qErrnoWarning(hr, "Could not read into socket stream buffer.");
return S_OK;
@@ -1268,28 +1241,6 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
return S_OK;
}
-HRESULT QNativeSocketEnginePrivate::handleWriteCompleted(IAsyncOperationWithProgress<UINT32, UINT32> *op, AsyncStatus status)
-{
- if (status == Error) {
- ComPtr<IAsyncInfo> info;
- HRESULT hr = op->QueryInterface(IID_PPV_ARGS(&info));
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to cast operation.");
- return S_OK;
- }
- HRESULT errorCode;
- hr = info->get_ErrorCode(&errorCode);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get error code.");
- return S_OK;
- }
- qErrnoWarning(errorCode, "A socket error occurred.");
- return S_OK;
- }
-
- return S_OK;
-}
-
HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args)
{
Q_Q(QNativeSocketEngine);
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index adb24a84c9..1d84c93f0a 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -202,7 +202,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::Storage::Streams::IBuffer> readBuffer;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> connectOp;
QBuffer readBytes;
QMutex readMutex;
@@ -219,7 +218,6 @@ private:
ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args);
HRESULT handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus);
- HRESULT handleWriteCompleted(ABI::Windows::Foundation::IAsyncOperationWithProgress<UINT32, UINT32> *, ABI::Windows::Foundation::AsyncStatus);
};
QT_END_NAMESPACE