diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2019-01-28 15:57:44 +0100 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2019-02-08 14:37:50 +0000 |
commit | c41efe7373ef207913cd27111aae8d3c48890efe (patch) | |
tree | fd1fe588ac752b81aec8e165d6e3183749e9073d /src/network | |
parent | 26ebdeff75d9f0f7b1ca2f82c35d7eaa013c0982 (diff) |
Schannel: slightly optimize memory-usage for encryption
Change-Id: I0f4b372ad3a0cd5e6730ed2e23e738fb06b2aad5
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/ssl/qsslsocket_schannel.cpp | 39 |
1 files changed, 15 insertions, 24 deletions
diff --git a/src/network/ssl/qsslsocket_schannel.cpp b/src/network/ssl/qsslsocket_schannel.cpp index 965e9bf2f3..e75f81bd36 100644 --- a/src/network/ssl/qsslsocket_schannel.cpp +++ b/src/network/ssl/qsslsocket_schannel.cpp @@ -142,12 +142,9 @@ Medium priority: - Setting cipher-suites (or ALG_ID) - People have survived without it in WinRT - - ALPN: - For HTTP2. Note: Windows 8.1 and up ONLY. Low priority: - Possibly make RAII wrappers for SecBuffer (which I commonly create QScopeGuards for) - - Perform the '@future' optimization in "transmit()" */ @@ -1188,23 +1185,21 @@ void QSslSocketBackendPrivate::transmit() qint64 totalBytesWritten = 0; qint64 writeBufferSize; while ((writeBufferSize = writeBuffer.size()) > 0) { - QByteArray plaintext; + const int headerSize = int(streamSizes.cbHeader); + const int trailerSize = int(streamSizes.cbTrailer); + // Try to read 'cbMaximumMessage' bytes from buffer before encrypting. + const int size = int(std::min(writeBufferSize, qint64(streamSizes.cbMaximumMessage))); + QByteArray fullMessage(headerSize + trailerSize + size, Qt::Uninitialized); { - // Try to read 'cbMaximumMessage' bytes from buffer before encrypting. - int size = int(std::min(writeBufferSize, qint64(streamSizes.cbMaximumMessage))); - plaintext.resize(size); // Use peek() here instead of read() so we don't lose data if encryption fails. - qint64 copied = writeBuffer.peek(plaintext.data(), size); + qint64 copied = writeBuffer.peek(fullMessage.data() + headerSize, size); Q_ASSERT(copied == size); } - QByteArray header(int(streamSizes.cbHeader), '\0'); - QByteArray trailer(int(streamSizes.cbTrailer), '\0'); SecBuffer inputBuffers[4]{ - // @future[0/1]: optimize by using one container for all fields... - createSecBuffer(header, SECBUFFER_STREAM_HEADER), - createSecBuffer(plaintext, SECBUFFER_DATA), - createSecBuffer(trailer, SECBUFFER_STREAM_TRAILER), + createSecBuffer(fullMessage.data(), headerSize, SECBUFFER_STREAM_HEADER), + createSecBuffer(fullMessage.data() + headerSize, size, SECBUFFER_DATA), + createSecBuffer(fullMessage.data() + headerSize + size, trailerSize, SECBUFFER_STREAM_TRAILER), createSecBuffer(nullptr, 0, SECBUFFER_EMPTY) }; SecBufferDesc message{ @@ -1220,18 +1215,14 @@ void QSslSocketBackendPrivate::transmit() return; } // Data was encrypted successfully, so we free() what we peek()ed earlier - writeBuffer.free(plaintext.length()); - - // trailer has been observed to change size, so resize them all (when needed) to be safe - header = header.left(int(inputBuffers[0].cbBuffer)); - plaintext = plaintext.left(int(inputBuffers[1].cbBuffer)); - trailer = trailer.left(int(inputBuffers[2].cbBuffer)); - const qint64 bytesWritten = plainSocket->write(header // @future[1/1]: ...because they need to be merged - + plaintext - + trailer); + writeBuffer.free(size); + + // The trailer's size is not final, so resize fullMessage to not send trailing junk + fullMessage.resize(inputBuffers[0].cbBuffer + inputBuffers[1].cbBuffer + inputBuffers[2].cbBuffer); + const qint64 bytesWritten = plainSocket->write(fullMessage); #ifdef QSSLSOCKET_DEBUG qCDebug(lcSsl) << "Wrote" << bytesWritten << "of total" - << header.length() + plaintext.length() + trailer.length() << "bytes"; + << fullMessage.length() << "bytes"; #endif if (bytesWritten >= 0) { totalBytesWritten += bytesWritten; |