1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2016 Intel Corporation.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtNetwork module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#ifndef QNATIVESOCKETENGINE_P_H
42#define QNATIVESOCKETENGINE_P_H
43
44//
45// W A R N I N G
46// -------------
47//
48// This file is not part of the Qt API. It exists purely as an
49// implementation detail. This header file may change from version to
50// version without notice, or even be removed.
51//
52// We mean it.
53//
54
55#include <QtNetwork/private/qtnetworkglobal_p.h>
56#include "QtNetwork/qhostaddress.h"
57#include "QtNetwork/qnetworkinterface.h"
58#include "private/qabstractsocketengine_p.h"
59#ifndef Q_OS_WIN
60# include "qplatformdefs.h"
61# include <netinet/in.h>
62#else
63# include <winsock2.h>
64# include <ws2tcpip.h>
65# include <mswsock.h>
66#endif
67
68QT_BEGIN_NAMESPACE
69
70#ifdef Q_OS_WIN
71# define QT_SOCKLEN_T int
72# define QT_SOCKOPTLEN_T int
73
74// The following definitions are copied from the MinGW header mswsock.h which
75// was placed in the public domain. The WSASendMsg and WSARecvMsg functions
76// were introduced with Windows Vista, so some Win32 headers are lacking them.
77// There are no known versions of Windows CE or Embedded that contain them.
78# ifndef WSAID_WSARECVMSG
79typedef INT (WINAPI *LPFN_WSARECVMSG)(SOCKET s, LPWSAMSG lpMsg,
80 LPDWORD lpdwNumberOfBytesRecvd,
81 LPWSAOVERLAPPED lpOverlapped,
82 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
83# define WSAID_WSARECVMSG {0xf689d7c8,0x6f1f,0x436b,{0x8a,0x53,0xe5,0x4f,0xe3,0x51,0xc3,0x22}}
84# endif // !WSAID_WSARECVMSG
85# ifndef WSAID_WSASENDMSG
86typedef struct {
87 LPWSAMSG lpMsg;
88 DWORD dwFlags;
89 LPDWORD lpNumberOfBytesSent;
90 LPWSAOVERLAPPED lpOverlapped;
91 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine;
92} WSASENDMSG, *LPWSASENDMSG;
93
94typedef INT (WSAAPI *LPFN_WSASENDMSG)(SOCKET s, LPWSAMSG lpMsg, DWORD dwFlags,
95 LPDWORD lpNumberOfBytesSent,
96 LPWSAOVERLAPPED lpOverlapped,
97 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
98
99# define WSAID_WSASENDMSG {0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}}
100# endif // !WSAID_WSASENDMSG
101#endif // Q_OS_WIN
102
103union qt_sockaddr {
104 sockaddr a;
105 sockaddr_in a4;
106 sockaddr_in6 a6;
107};
108
109namespace {
110namespace SetSALen {
111 template <typename T> void set(T *sa, typename std::enable_if<(&T::sa_len, true), QT_SOCKLEN_T>::type len)
112 { sa->sa_len = len; }
113 template <typename T> void set(T *sin6, typename std::enable_if<(&T::sin6_len, true), QT_SOCKLEN_T>::type len)
114 { sin6->sin6_len = len; }
115 template <typename T> void set(T *, ...) {}
116}
117}
118
119class QNativeSocketEnginePrivate;
120#ifndef QT_NO_NETWORKINTERFACE
121class QNetworkInterface;
122#endif
123
124class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine
125{
126 Q_OBJECT
127public:
128 QNativeSocketEngine(QObject *parent = nullptr);
129 ~QNativeSocketEngine();
130
131 bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) override;
132 bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState) override;
133
134 qintptr socketDescriptor() const override;
135
136 bool isValid() const override;
137
138 bool connectToHost(const QHostAddress &address, quint16 port) override;
139 bool connectToHostByName(const QString &name, quint16 port) override;
140 bool bind(const QHostAddress &address, quint16 port) override;
141 bool listen() override;
142 int accept() override;
143 void close() override;
144
145 qint64 bytesAvailable() const override;
146
147 qint64 read(char *data, qint64 maxlen) override;
148 qint64 write(const char *data, qint64 len) override;
149
150#ifndef QT_NO_UDPSOCKET
151#ifndef QT_NO_NETWORKINTERFACE
152 bool joinMulticastGroup(const QHostAddress &groupAddress,
153 const QNetworkInterface &iface) override;
154 bool leaveMulticastGroup(const QHostAddress &groupAddress,
155 const QNetworkInterface &iface) override;
156 QNetworkInterface multicastInterface() const override;
157 bool setMulticastInterface(const QNetworkInterface &iface) override;
158#endif
159
160 bool hasPendingDatagrams() const override;
161 qint64 pendingDatagramSize() const override;
162#endif // QT_NO_UDPSOCKET
163
164 qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = nullptr,
165 PacketHeaderOptions = WantNone) override;
166 qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) override;
167 qint64 bytesToWrite() const override;
168
169#if 0 // currently unused
170 qint64 receiveBufferSize() const;
171 void setReceiveBufferSize(qint64 bufferSize);
172
173 qint64 sendBufferSize() const;
174 void setSendBufferSize(qint64 bufferSize);
175#endif
176
177 int option(SocketOption option) const override;
178 bool setOption(SocketOption option, int value) override;
179
180 bool waitForRead(int msecs = 30000, bool *timedOut = nullptr) override;
181 bool waitForWrite(int msecs = 30000, bool *timedOut = nullptr) override;
182 bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
183 bool checkRead, bool checkWrite,
184 int msecs = 30000, bool *timedOut = nullptr) override;
185
186 bool isReadNotificationEnabled() const override;
187 void setReadNotificationEnabled(bool enable) override;
188 bool isWriteNotificationEnabled() const override;
189 void setWriteNotificationEnabled(bool enable) override;
190 bool isExceptionNotificationEnabled() const override;
191 void setExceptionNotificationEnabled(bool enable) override;
192
193public Q_SLOTS:
194 // non-virtual override;
195 void connectionNotification();
196
197private:
198 Q_DECLARE_PRIVATE(QNativeSocketEngine)
199 Q_DISABLE_COPY_MOVE(QNativeSocketEngine)
200};
201
202class QSocketNotifier;
203
204class QNativeSocketEnginePrivate : public QAbstractSocketEnginePrivate
205{
206 Q_DECLARE_PUBLIC(QNativeSocketEngine)
207public:
208 QNativeSocketEnginePrivate();
209 ~QNativeSocketEnginePrivate();
210
211 qintptr socketDescriptor;
212
213 QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier;
214
215#if defined(Q_OS_WIN)
216 LPFN_WSASENDMSG sendmsg;
217 LPFN_WSARECVMSG recvmsg;
218# endif
219 enum ErrorString {
220 NonBlockingInitFailedErrorString,
221 BroadcastingInitFailedErrorString,
222 NoIpV6ErrorString,
223 RemoteHostClosedErrorString,
224 TimeOutErrorString,
225 ResourceErrorString,
226 OperationUnsupportedErrorString,
227 ProtocolUnsupportedErrorString,
228 InvalidSocketErrorString,
229 HostUnreachableErrorString,
230 NetworkUnreachableErrorString,
231 AccessErrorString,
232 ConnectionTimeOutErrorString,
233 ConnectionRefusedErrorString,
234 AddressInuseErrorString,
235 AddressNotAvailableErrorString,
236 AddressProtectedErrorString,
237 DatagramTooLargeErrorString,
238 SendDatagramErrorString,
239 ReceiveDatagramErrorString,
240 WriteErrorString,
241 ReadErrorString,
242 PortInuseErrorString,
243 NotSocketErrorString,
244 InvalidProxyTypeString,
245 TemporaryErrorString,
246 NetworkDroppedConnectionErrorString,
247 ConnectionResetErrorString,
248
249 UnknownSocketErrorString = -1
250 };
251
252 void setError(QAbstractSocket::SocketError error, ErrorString errorString) const;
253 QHostAddress adjustAddressProtocol(const QHostAddress &address) const;
254
255 // native functions
256 int option(QNativeSocketEngine::SocketOption option) const;
257 bool setOption(QNativeSocketEngine::SocketOption option, int value);
258
259 bool createNewSocket(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol &protocol);
260
261 bool nativeConnect(const QHostAddress &address, quint16 port);
262 bool nativeBind(const QHostAddress &address, quint16 port);
263 bool nativeListen(int backlog);
264 int nativeAccept();
265#ifndef QT_NO_NETWORKINTERFACE
266 bool nativeJoinMulticastGroup(const QHostAddress &groupAddress,
267 const QNetworkInterface &iface);
268 bool nativeLeaveMulticastGroup(const QHostAddress &groupAddress,
269 const QNetworkInterface &iface);
270 QNetworkInterface nativeMulticastInterface() const;
271 bool nativeSetMulticastInterface(const QNetworkInterface &iface);
272#endif
273 qint64 nativeBytesAvailable() const;
274
275 bool nativeHasPendingDatagrams() const;
276 qint64 nativePendingDatagramSize() const;
277 qint64 nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header,
278 QAbstractSocketEngine::PacketHeaderOptions options);
279 qint64 nativeSendDatagram(const char *data, qint64 length, const QIpPacketHeader &header);
280 qint64 nativeRead(char *data, qint64 maxLength);
281 qint64 nativeWrite(const char *data, qint64 length);
282 int nativeSelect(int timeout, bool selectForRead) const;
283 int nativeSelect(int timeout, bool checkRead, bool checkWrite,
284 bool *selectForRead, bool *selectForWrite) const;
285
286 void nativeClose();
287
288 bool checkProxy(const QHostAddress &address);
289 bool fetchConnectionParameters();
290
291#if QT_CONFIG(networkinterface)
292 static uint scopeIdFromString(const QString &scopeid)
293 { return QNetworkInterface::interfaceIndexFromName(scopeid); }
294#endif
295
296 /*! \internal
297 Sets \a address and \a port in the \a aa sockaddr structure and the size in \a sockAddrSize.
298 The address \a is converted to IPv6 if the current socket protocol is also IPv6.
299 */
300 void setPortAndAddress(quint16 port, const QHostAddress &address, qt_sockaddr *aa, QT_SOCKLEN_T *sockAddrSize)
301 {
302 if (address.protocol() == QAbstractSocket::IPv6Protocol
303 || address.protocol() == QAbstractSocket::AnyIPProtocol
304 || socketProtocol == QAbstractSocket::IPv6Protocol
305 || socketProtocol == QAbstractSocket::AnyIPProtocol) {
306 memset(&aa->a6, 0, sizeof(sockaddr_in6));
307 aa->a6.sin6_family = AF_INET6;
308#if QT_CONFIG(networkinterface)
309 aa->a6.sin6_scope_id = scopeIdFromString(address.scopeId());
310#endif
311 aa->a6.sin6_port = htons(port);
312 Q_IPV6ADDR tmp = address.toIPv6Address();
313 memcpy(&aa->a6.sin6_addr, &tmp, sizeof(tmp));
314 *sockAddrSize = sizeof(sockaddr_in6);
315 SetSALen::set(&aa->a, sizeof(sockaddr_in6));
316 } else {
317 memset(&aa->a, 0, sizeof(sockaddr_in));
318 aa->a4.sin_family = AF_INET;
319 aa->a4.sin_port = htons(port);
320 aa->a4.sin_addr.s_addr = htonl(address.toIPv4Address());
321 *sockAddrSize = sizeof(sockaddr_in);
322 SetSALen::set(&aa->a, sizeof(sockaddr_in));
323 }
324 }
325
326};
327
328QT_END_NAMESPACE
329
330#endif // QNATIVESOCKETENGINE_P_H
331