summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2017-08-20 15:50:41 -0700
committerThiago Macieira <thiago.macieira@intel.com>2017-11-14 15:54:51 +0000
commitaaa187cd9951b71127c11c375e6a3954a187e1d3 (patch)
tree54dcee410994b3d64058ed6dde9e95c519fee83a /src/network
parentaa494d826ace02ffff5f29ae20b7738630913777 (diff)
QAbstractSocket: Add socketOption for the Path MTU
This allow retrieving the value of the known PMTU for the current socket. This works on Linux (IPv6 and IPv4) and FreeBSD (IPv6 only) -- the other OSes don't have the necessary API. Note: do we need add IP_MTU_DISCOVER? Change-Id: I6e9274c1e7444ad48c81fffd14dcaf97a18ce335 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/network')
-rw-r--r--src/network/socket/qabstractsocket.cpp13
-rw-r--r--src/network/socket/qabstractsocket.h3
-rw-r--r--src/network/socket/qabstractsocketengine_p.h3
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp30
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp15
-rw-r--r--src/network/socket/qnativesocketengine_winrt.cpp2
6 files changed, 60 insertions, 6 deletions
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 6d47540b75..98baa0c047 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -387,6 +387,11 @@
(see \l{QAbstractSocket::}{setReadBufferSize()}).
This enum value has been introduced in Qt 5.3.
+ \value PathMtuSocketOption Retrieves the Path Maximum Transmission Unit
+ (PMTU) value currently known by the IP stack, if any. Some IP stacks also
+ allow setting the MTU for transmission.
+ This enum value was introduced in Qt 5.11.
+
Possible values for \e{TypeOfServiceOption} are:
\table
@@ -2023,6 +2028,10 @@ void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, cons
case ReceiveBufferSizeSocketOption:
d_func()->socketEngine->setOption(QAbstractSocketEngine::ReceiveBufferSocketOption, value.toInt());
break;
+
+ case PathMtuSocketOption:
+ d_func()->socketEngine->setOption(QAbstractSocketEngine::PathMtuInformation, value.toInt());
+ break;
}
}
@@ -2065,6 +2074,10 @@ QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption option)
case ReceiveBufferSizeSocketOption:
ret = d_func()->socketEngine->option(QAbstractSocketEngine::ReceiveBufferSocketOption);
break;
+
+ case PathMtuSocketOption:
+ ret = d_func()->socketEngine->option(QAbstractSocketEngine::PathMtuInformation);
+ break;
}
if (ret == -1)
return QVariant();
diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h
index ba499ddf7d..6d5e57ac52 100644
--- a/src/network/socket/qabstractsocket.h
+++ b/src/network/socket/qabstractsocket.h
@@ -120,7 +120,8 @@ public:
MulticastLoopbackOption, // IP_MULTICAST_LOOPBACK
TypeOfServiceOption, //IP_TOS
SendBufferSizeSocketOption, //SO_SNDBUF
- ReceiveBufferSizeSocketOption //SO_RCVBUF
+ ReceiveBufferSizeSocketOption, //SO_RCVBUF
+ PathMtuSocketOption // IP_MTU
};
Q_ENUM(SocketOption)
enum BindFlag {
diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h
index 0cb519ce90..b15dd73c96 100644
--- a/src/network/socket/qabstractsocketengine_p.h
+++ b/src/network/socket/qabstractsocketengine_p.h
@@ -105,7 +105,8 @@ public:
TypeOfServiceOption,
ReceivePacketInformation,
ReceiveHopLimit,
- MaxStreamsSocketOption
+ MaxStreamsSocketOption,
+ PathMtuInformation
};
enum PacketHeaderOption {
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index cb0a521360..b380b0f7d6 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -226,6 +226,20 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt,
#endif
}
break;
+
+ case QNativeSocketEngine::PathMtuInformation:
+ if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
+#ifdef IPV6_MTU
+ level = IPPROTO_IPV6;
+ n = IPV6_MTU;
+#endif
+ } else {
+#ifdef IP_MTU
+ level = IPPROTO_IP;
+ n = IP_MTU;
+#endif
+ }
+ break;
}
}
@@ -331,6 +345,20 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co
return -1;
}
+ case QNativeSocketEngine::PathMtuInformation:
+#if defined(IPV6_PATHMTU) && !defined(IPV6_MTU)
+ // Prefer IPV6_MTU (handled by convertToLevelAndOption), if available
+ // (Linux); fall back to IPV6_PATHMTU otherwise (FreeBSD):
+ if (socketProtocol == QAbstractSocket::IPv6Protocol) {
+ ip6_mtuinfo mtuinfo;
+ QT_SOCKOPTLEN_T len = sizeof(mtuinfo);
+ if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_PATHMTU, &mtuinfo, &len) == 0)
+ return int(mtuinfo.ip6m_mtu);
+ return -1;
+ }
+#endif
+ break;
+
default:
break;
}
@@ -420,6 +448,8 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
}
#endif
+ if (n == -1)
+ return false;
return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0;
}
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 1ec3df842f..fb31607e2c 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -209,7 +209,7 @@ static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt
static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt,
QAbstractSocket::NetworkLayerProtocol socketProtocol, int &level, int &n)
{
- n = 0;
+ n = -1;
level = SOL_SOCKET; // default
switch (opt) {
@@ -281,6 +281,9 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt,
n = IP_HOPLIMIT;
}
break;
+
+ case QAbstractSocketEngine::PathMtuInformation:
+ break; // not supported on Windows
}
}
@@ -471,9 +474,11 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co
QT_SOCKOPTLEN_T len = sizeof(v);
convertToLevelAndOption(opt, socketProtocol, level, n);
- if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) == 0)
- return v;
- WS_ERROR_DEBUG(WSAGetLastError());
+ if (n != -1) {
+ if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) == 0)
+ return v;
+ WS_ERROR_DEBUG(WSAGetLastError());
+ }
return -1;
}
@@ -514,6 +519,8 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
int n, level;
convertToLevelAndOption(opt, socketProtocol, level, n);
+ if (n == -1)
+ return false;
if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) {
WS_ERROR_DEBUG(WSAGetLastError());
return false;
diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp
index 0baf5c9e21..9df5f0c500 100644
--- a/src/network/socket/qnativesocketengine_winrt.cpp
+++ b/src/network/socket/qnativesocketengine_winrt.cpp
@@ -1514,6 +1514,7 @@ int QNativeSocketEnginePrivate::option(QAbstractSocketEngine::SocketOption opt)
case QAbstractSocketEngine::MulticastLoopbackOption:
case QAbstractSocketEngine::TypeOfServiceOption:
case QAbstractSocketEngine::MaxStreamsSocketOption:
+ case QAbstractSocketEngine::PathMtuInformation:
default:
return -1;
}
@@ -1573,6 +1574,7 @@ bool QNativeSocketEnginePrivate::setOption(QAbstractSocketEngine::SocketOption o
case QAbstractSocketEngine::MulticastLoopbackOption:
case QAbstractSocketEngine::TypeOfServiceOption:
case QAbstractSocketEngine::MaxStreamsSocketOption:
+ case QAbstractSocketEngine::PathMtuInformation:
default:
return false;
}