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 
68 QT_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
79 typedef 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
86 typedef struct {
87   LPWSAMSG lpMsg;
88   DWORD dwFlags;
89   LPDWORD lpNumberOfBytesSent;
90   LPWSAOVERLAPPED lpOverlapped;
91   LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine;
92 } WSASENDMSG, *LPWSASENDMSG;
93 
94 typedef 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 
103 union qt_sockaddr {
104     sockaddr a;
105     sockaddr_in a4;
106     sockaddr_in6 a6;
107 };
108 
109 namespace {
110 namespace SetSALen {
set(T * sa,typename std::enable_if<(& T::sa_len,true),QT_SOCKLEN_T>::type len)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; }
set(T * sin6,typename std::enable_if<(& T::sin6_len,true),QT_SOCKLEN_T>::type 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; }
set(T *,...)115     template <typename T> void set(T *, ...) {}
116 }
117 }
118 
119 class QNativeSocketEnginePrivate;
120 #ifndef QT_NO_NETWORKINTERFACE
121 class QNetworkInterface;
122 #endif
123 
124 class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine
125 {
126     Q_OBJECT
127 public:
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 
193 public Q_SLOTS:
194     // non-virtual override;
195     void connectionNotification();
196 
197 private:
198     Q_DECLARE_PRIVATE(QNativeSocketEngine)
199     Q_DISABLE_COPY_MOVE(QNativeSocketEngine)
200 };
201 
202 class QSocketNotifier;
203 
204 class QNativeSocketEnginePrivate : public QAbstractSocketEnginePrivate
205 {
206     Q_DECLARE_PUBLIC(QNativeSocketEngine)
207 public:
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)
scopeIdFromString(const QString & scopeid)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      */
setPortAndAddress(quint16 port,const QHostAddress & address,qt_sockaddr * aa,QT_SOCKLEN_T * sockAddrSize)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 
328 QT_END_NAMESPACE
329 
330 #endif // QNATIVESOCKETENGINE_P_H
331