1/****************************************************************************
2**
3** Copyright (C) 2019 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QString>
30#include <QtTest/QtTest>
31#ifdef QT_NETWORK_LIB
32#include <QtNetwork/QHostInfo>
33#include <QtNetwork/QHostAddress>
34#include <QtNetwork/QAbstractSocket>
35#include <QtNetwork/QTcpSocket>
36#endif
37
38#ifdef Q_OS_UNIX
39#include <sys/types.h>
40#include <sys/socket.h>
41#include <netinet/in.h>
42#include <unistd.h>
43#endif
44
45class QtNetworkSettings
46{
47public:
48
49 static QString serverLocalName()
50 {
51 return QString("qt-test-server");
52 }
53 static QString serverDomainName()
54 {
55#ifdef QT_TEST_SERVER_DOMAIN
56 return QString(QT_TEST_SERVER_DOMAIN); // Defined in testserver feature
57#else
58 return QString("qt-test-net");
59#endif
60 }
61 static QString serverName()
62 {
63 return serverLocalName() + "." + serverDomainName();
64 }
65 static QString winServerName()
66 {
67 return serverName();
68 }
69 static QString wildcardServerName()
70 {
71 return "qt-test-server.wildcard.dev." + serverDomainName();
72 }
73
74#ifdef QT_NETWORK_LIB
75 static QHostAddress getServerIpImpl(const QString &serverName)
76 {
77 const QHostInfo info = QHostInfo::fromName(name: serverName);
78 if (info.error()) {
79 QTest::qFail(qPrintable(info.errorString()), __FILE__, __LINE__);
80 return QHostAddress();
81 }
82 return info.addresses().constFirst();
83 }
84
85 static QHostAddress serverIP()
86 {
87 return getServerIpImpl(serverName: serverName());
88 }
89#endif
90
91 static bool compareReplyIMAP(QByteArray const& actual)
92 {
93 // Server greeting may contain capability, version and server name
94 // But spec only requires "* OK" and "\r\n"
95 // Match against a prefix and postfix that covers all Cyrus versions
96 if (actual.startsWith(c: "* OK ")
97 && actual.endsWith(c: "server ready\r\n")) {
98 return true;
99 }
100
101 return false;
102 }
103
104 static bool compareReplyIMAPSSL(QByteArray const& actual)
105 {
106 return compareReplyIMAP(actual);
107 }
108
109 static bool compareReplyFtp(QByteArray const& actual)
110 {
111 // output would be e.g. "220 (vsFTPd 2.3.5)\r\n221 Goodbye.\r\n"
112 QRegularExpression ftpVersion(QRegularExpression::anchoredPattern(QStringLiteral("220 \\(vsFTPd \\d+\\.\\d+.\\d+\\)\\r\\n221 Goodbye.\\r\\n")));
113 return ftpVersion.match(subject: actual).hasMatch();
114 }
115
116 static bool hasIPv6()
117 {
118#ifdef Q_OS_UNIX
119 int s = ::socket(AF_INET6, SOCK_DGRAM, protocol: 0);
120 if (s == -1)
121 return false;
122 else {
123 struct sockaddr_in6 addr;
124 memset(s: &addr, c: 0, n: sizeof(addr));
125 addr.sin6_family = AF_INET6;
126 memcpy(dest: &addr.sin6_addr, src: &in6addr_loopback, n: sizeof(in6_addr));
127 if (-1 == ::bind(fd: s, addr: (sockaddr*)&addr, len: sizeof(addr))) {
128 ::close(fd: s);
129 return false;
130 }
131 }
132 ::close(fd: s);
133#endif
134 return true;
135 }
136
137 static bool canBindToLowPorts()
138 {
139#ifdef Q_OS_UNIX
140 if (geteuid() == 0)
141 return true;
142 if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave)
143 return true;
144 // ### Which versions of iOS, watchOS and such does Apple's opening of
145 // all ports apply to?
146 return false;
147#else
148 // Windows
149 return true;
150#endif
151 }
152
153
154#ifdef QT_NETWORK_LIB
155 static bool verifyTestNetworkSettings()
156 {
157 QHostInfo testServerResult = QHostInfo::fromName(name: QtNetworkSettings::serverName());
158 if (testServerResult.error() != QHostInfo::NoError) {
159 qWarning() << "Could not lookup" << QtNetworkSettings::serverName();
160 qWarning() << "Please configure the test environment!";
161 qWarning() << "See /etc/hosts or network-settings.h";
162 return false;
163 }
164 return true;
165 }
166
167 static bool verifyConnection(QString serverName, quint16 port, quint32 retry = 60)
168 {
169 QTcpSocket socket;
170 for (quint32 i = 1; i < retry; i++) {
171 socket.connectToHost(hostName: serverName, port);
172 if (socket.waitForConnected(msecs: 1000))
173 return true;
174 // Wait for service to start up
175 QTest::qWait(ms: 1000);
176 }
177 socket.connectToHost(hostName: serverName, port);
178 return socket.waitForConnected(msecs: 1000);
179 }
180
181 // Helper function for usage with QVERIFY2 on sockets.
182 static QByteArray msgSocketError(const QAbstractSocket &s)
183 {
184 QString result;
185 QDebug debug(&result);
186 debug.nospace();
187 debug.noquote();
188 if (!s.localAddress().isNull())
189 debug << "local=" << s.localAddress().toString() << ':' << s.localPort();
190 if (!s.peerAddress().isNull())
191 debug << ", peer=" << s.peerAddress().toString() << ':' << s.peerPort();
192 debug << ", type=" << s.socketType() << ", state=" << s.state()
193 << ", error=" << s.error() << ": " << s.errorString();
194 return result.toLocal8Bit();
195 }
196#endif // QT_NETWORK_LIB
197
198 static QString ftpServerName()
199 {
200#ifdef QT_TEST_SERVER_NAME
201 return QString("vsftpd.") % serverDomainName();
202#else
203 return serverName();
204#endif
205 }
206 static QString ftpProxyServerName()
207 {
208#ifdef QT_TEST_SERVER_NAME
209 return QString("ftp-proxy.") % serverDomainName();
210#else
211 return serverName();
212#endif
213 }
214 static QString httpServerName()
215 {
216#ifdef QT_TEST_SERVER_NAME
217 return QString("apache2.") % serverDomainName();
218#else
219 return serverName();
220#endif
221 }
222 static QString httpProxyServerName()
223 {
224#ifdef QT_TEST_SERVER_NAME
225 return QString("squid.") % serverDomainName();
226#else
227 return serverName();
228#endif
229 }
230 static QString socksProxyServerName()
231 {
232#ifdef QT_TEST_SERVER_NAME
233 return QString("danted.") % serverDomainName();
234#else
235 return serverName();
236#endif
237 }
238 static QString imapServerName()
239 {
240#ifdef QT_TEST_SERVER_NAME
241 return QString("cyrus.") % serverDomainName();
242#else
243 return serverName();
244#endif
245 }
246
247 static QString echoServerName()
248 {
249#ifdef QT_TEST_SERVER_NAME
250 return QString("echo.") % serverDomainName();
251#else
252 return serverName();
253#endif
254 }
255
256 static QString firewallServerName()
257 {
258#ifdef QT_TEST_SERVER_NAME
259 return QString("iptables.") % serverDomainName();
260#else
261 return serverName();
262#endif
263 }
264
265 static QString hostWithServiceOnPort(int port)
266 {
267#if !defined(QT_TEST_SERVER)
268 Q_UNUSED(port);
269 return serverName();
270#else
271 switch (port) {
272 case 13:
273 case 22:
274 case 139:
275 return serverName(); // No such things in docker (yet?)
276 case 7:
277 return echoServerName();
278 case 21:
279 return ftpServerName();
280 case 80:
281 case 443:
282 return httpServerName();
283 case 143:
284 return imapServerName();
285 case 3128:
286 case 3129:
287 case 3130:
288 return httpProxyServerName();
289 case 1080:
290 case 1081:
291 return socksProxyServerName();
292 case 2121:
293 return ftpProxyServerName();
294 default:
295 return serverName();
296 }
297#endif // QT_TEST_SERVER
298 }
299
300#ifdef QT_NETWORK_LIB
301 static QHostAddress imapServerIp()
302 {
303 return getServerIpImpl(serverName: imapServerName());
304 }
305
306 static QHostAddress httpServerIp()
307 {
308 return getServerIpImpl(serverName: httpServerName());
309 }
310
311 static QHostAddress httpProxyServerIp()
312 {
313 return getServerIpImpl(serverName: httpProxyServerName());
314 }
315
316 static QHostAddress socksProxyServerIp()
317 {
318 return getServerIpImpl(serverName: socksProxyServerName());
319 }
320
321 static QHostAddress ftpProxyServerIp()
322 {
323 return getServerIpImpl(serverName: ftpProxyServerName());
324 }
325
326 static QHostAddress ftpServerIp()
327 {
328 return getServerIpImpl(serverName: ftpServerName());
329 }
330
331 static QHostAddress firewallServerIp()
332 {
333 return getServerIpImpl(serverName: firewallServerName());
334 }
335
336#endif // QT_NETWORK_LIB
337};
338

source code of qtbase/tests/auto/network-settings.h