summaryrefslogtreecommitdiffstats
path: root/src/network/socket/qnativesocketengine_win.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2015-03-10 15:09:29 -0700
committerThiago Macieira <thiago.macieira@intel.com>2015-08-22 22:26:30 +0000
commitef05ad0ac500c10b1a3ae254d8a07968d6cf0c9e (patch)
treef2545760293240883c22bffe71d4fab48484dfc5 /src/network/socket/qnativesocketengine_win.cpp
parent5b38454714fdbf8d4acffe482aaa32b91a4b5d98 (diff)
QNativeSocketEngine: use sendmsg/recvmsg instead of sendto/recvfrom
We'll need to use these functions instead of the ones we're currently using in order to access the ancillary data. Note that on Windows the two functions aren't globals, but must be obtained via ioctl, which means they can fail. If they do, we fall back to using WSARecvFrom/WSASendTo Change-Id: Iee8cbc07c4434ce9b560ffff13ca4284acd24132 Reviewed-by: Richard J. Moore <rich@kde.org>
Diffstat (limited to 'src/network/socket/qnativesocketengine_win.cpp')
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp82
1 files changed, 55 insertions, 27 deletions
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index ed376eed95..9171ee36e0 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -420,6 +420,20 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
WS_ERROR_DEBUG(err);
}
}
+
+ // get the pointer to sendmsg and recvmsg
+ DWORD bytesReturned;
+ GUID recvmsgguid = WSAID_WSARECVMSG;
+ if (WSAIoctl(socketDescriptor, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &recvmsgguid, sizeof(recvmsgguid),
+ &recvmsg, sizeof(recvmsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR)
+ recvmsg = 0;
+
+ GUID sendmsgguid = WSAID_WSASENDMSG;
+ if (WSAIoctl(socketDescriptor, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &sendmsgguid, sizeof(sendmsgguid),
+ &sendmsg, sizeof(sendmsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR)
+ sendmsg = 0;
#endif
socketDescriptor = socket;
@@ -1196,33 +1210,39 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
return ret;
}
+#ifdef Q_OS_WINCE
+// Windows CE has no support for sendmsg or recvmsg. We set it to null here to simplify the code below.
+static int (*const recvmsg)(...) = 0;
+static int (*const sendmsg)(...) = 0;
+#endif
qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header,
QAbstractSocketEngine::PacketHeaderOptions options)
{
- qint64 ret = 0;
-
+ WSAMSG msg;
+ WSABUF buf;
qt_sockaddr aa;
+ char c;
+ memset(&msg, 0, sizeof(msg));
memset(&aa, 0, sizeof(aa));
- QT_SOCKLEN_T sz;
- sz = sizeof(aa);
- WSABUF buf;
- buf.buf = data;
- buf.len = maxLength;
-#if !defined(Q_OS_WINCE)
- buf.buf = data;
- buf.len = maxLength;
-#else
- char tmpChar;
- buf.buf = data ? data : &tmpChar;
- buf.len = maxLength;
-#endif
+ // we need to receive at least one byte, even if our user isn't interested in it
+ buf.buf = maxLength ? data : &c;
+ buf.len = maxLength ? maxLength : 1;
+ msg.lpBuffers = &buf;
+ msg.dwBufferCount = 1;
+ msg.name = reinterpret_cast<LPSOCKADDR>(&aa);
+ msg.namelen = sizeof(aa);
DWORD flags = 0;
DWORD bytesRead = 0;
- int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, &aa.a, &sz,0,0);
- if (wsaRet == SOCKET_ERROR) {
+ qint64 ret;
+
+ if (recvmsg)
+ ret = recvmsg(socketDescriptor, &msg, &bytesRead, 0,0);
+ else
+ ret = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, msg.name, &msg.namelen,0,0);
+ if (ret == SOCKET_ERROR) {
int err = WSAGetLastError();
if (err == WSAEMSGSIZE) {
// it is ok the buffer was to small if bytesRead is larger than
@@ -1256,26 +1276,34 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL
qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len,
const QIpPacketHeader &header)
{
- qint64 ret = -1;
- struct sockaddr_in sockAddrIPv4;
- qt_sockaddr_in6 sockAddrIPv6;
- struct sockaddr *sockAddrPtr = 0;
- QT_SOCKLEN_T sockAddrSize = 0;
-
- setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, header.destinationPort,
- header.destinationAddress, &sockAddrPtr, &sockAddrSize);
-
+ WSAMSG msg;
WSABUF buf;
+ qt_sockaddr aa;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&aa, 0, sizeof(aa));
#if !defined(Q_OS_WINCE)
buf.buf = len ? (char*)data : 0;
#else
char tmp;
buf.buf = len ? (char*)data : &tmp;
#endif
+ msg.lpBuffers = &buf;
+ msg.dwBufferCount = 1;
buf.len = len;
+
+ setPortAndAddress(&aa.a4, &aa.a6, header.destinationPort,
+ header.destinationAddress, &msg.name, &msg.namelen);
+
DWORD flags = 0;
DWORD bytesSent = 0;
- if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) == SOCKET_ERROR) {
+ qint64 ret = -1;
+ if (sendmsg) {
+ ret = sendmsg(socketDescriptor, &msg, flags, &bytesSent, 0,0);
+ } else {
+ ret = ::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, msg.name, msg.namelen, 0,0);
+ }
+ if (ret == SOCKET_ERROR) {
int err = WSAGetLastError();
WS_ERROR_DEBUG(err);
switch (err) {