1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // Copyright (C) 2016 Intel Corporation. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #ifndef QNATIVESOCKETENGINE_P_H |
6 | #define QNATIVESOCKETENGINE_P_H |
7 | |
8 | // |
9 | // W A R N I N G |
10 | // ------------- |
11 | // |
12 | // This file is not part of the Qt API. It exists purely as an |
13 | // implementation detail. This header file may change from version to |
14 | // version without notice, or even be removed. |
15 | // |
16 | // We mean it. |
17 | // |
18 | |
19 | #include <QtNetwork/private/qtnetworkglobal_p.h> |
20 | #include "QtNetwork/qhostaddress.h" |
21 | #include "QtNetwork/qnetworkinterface.h" |
22 | #include "private/qabstractsocketengine_p.h" |
23 | #include "qplatformdefs.h" |
24 | |
25 | #ifndef Q_OS_WIN |
26 | # include <netinet/in.h> |
27 | #else |
28 | # include <winsock2.h> |
29 | # include <ws2tcpip.h> |
30 | # include <mswsock.h> |
31 | #endif |
32 | |
33 | QT_BEGIN_NAMESPACE |
34 | |
35 | #ifdef Q_OS_WIN |
36 | # define QT_SOCKLEN_T int |
37 | # define QT_SOCKOPTLEN_T int |
38 | #endif |
39 | |
40 | namespace { |
41 | namespace SetSALen { |
42 | template <typename T> void set(T *sa, typename std::enable_if<(&T::sa_len, true), QT_SOCKLEN_T>::type len) |
43 | { sa->sa_len = len; } |
44 | template <typename T> void set(T *sa, typename std::enable_if<(&T::sin_len, true), QT_SOCKLEN_T>::type len) |
45 | { sa->sin_len = len; } |
46 | template <typename T> void set(T *sin6, typename std::enable_if<(&T::sin6_len, true), QT_SOCKLEN_T>::type len) |
47 | { sin6->sin6_len = len; } |
48 | template <typename T> void set(T *, ...) {} |
49 | } |
50 | |
51 | inline QT_SOCKLEN_T setSockaddr(sockaddr_in *sin, const QHostAddress &addr, quint16 port = 0) |
52 | { |
53 | *sin = {}; |
54 | SetSALen::set(sin, sizeof(*sin)); |
55 | sin->sin_family = AF_INET; |
56 | sin->sin_port = htons(hostshort: port); |
57 | sin->sin_addr.s_addr = htonl(hostlong: addr.toIPv4Address()); |
58 | return sizeof(*sin); |
59 | } |
60 | |
61 | inline QT_SOCKLEN_T setSockaddr(sockaddr_in6 *sin6, const QHostAddress &addr, quint16 port = 0) |
62 | { |
63 | *sin6 = {}; |
64 | SetSALen::set(sin6, sizeof(*sin6)); |
65 | sin6->sin6_family = AF_INET6; |
66 | sin6->sin6_port = htons(hostshort: port); |
67 | memcpy(dest: sin6->sin6_addr.s6_addr, src: addr.toIPv6Address().c, n: sizeof(sin6->sin6_addr)); |
68 | #if QT_CONFIG(networkinterface) |
69 | sin6->sin6_scope_id = QNetworkInterface::interfaceIndexFromName(name: addr.scopeId()); |
70 | #else |
71 | // it had better be a number then, if it is not empty |
72 | sin6->sin6_scope_id = addr.scopeId().toUInt(); |
73 | #endif |
74 | return sizeof(*sin6); |
75 | } |
76 | |
77 | inline QT_SOCKLEN_T setSockaddr(sockaddr *sa, const QHostAddress &addr, quint16 port = 0) |
78 | { |
79 | switch (addr.protocol()) { |
80 | case QHostAddress::IPv4Protocol: |
81 | return setSockaddr(sin: reinterpret_cast<sockaddr_in *>(sa), addr, port); |
82 | |
83 | case QHostAddress::IPv6Protocol: |
84 | case QHostAddress::AnyIPProtocol: |
85 | return setSockaddr(sin6: reinterpret_cast<sockaddr_in6 *>(sa), addr, port); |
86 | |
87 | case QHostAddress::UnknownNetworkLayerProtocol: |
88 | break; |
89 | } |
90 | *sa = {}; |
91 | sa->sa_family = AF_UNSPEC; |
92 | return 0; |
93 | } |
94 | } // unnamed namespace |
95 | |
96 | class QNativeSocketEnginePrivate; |
97 | #ifndef QT_NO_NETWORKINTERFACE |
98 | class QNetworkInterface; |
99 | #endif |
100 | |
101 | class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine |
102 | { |
103 | Q_OBJECT |
104 | public: |
105 | QNativeSocketEngine(QObject *parent = nullptr); |
106 | ~QNativeSocketEngine(); |
107 | |
108 | bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) override; |
109 | bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState) override; |
110 | |
111 | qintptr socketDescriptor() const override; |
112 | |
113 | bool isValid() const override; |
114 | |
115 | bool connectToHost(const QHostAddress &address, quint16 port) override; |
116 | bool connectToHostByName(const QString &name, quint16 port) override; |
117 | bool bind(const QHostAddress &address, quint16 port) override; |
118 | bool listen(int backlog) override; |
119 | qintptr accept() override; |
120 | void close() override; |
121 | |
122 | qint64 bytesAvailable() const override; |
123 | |
124 | qint64 read(char *data, qint64 maxlen) override; |
125 | qint64 write(const char *data, qint64 len) override; |
126 | |
127 | #ifndef QT_NO_UDPSOCKET |
128 | #ifndef QT_NO_NETWORKINTERFACE |
129 | bool joinMulticastGroup(const QHostAddress &groupAddress, |
130 | const QNetworkInterface &iface) override; |
131 | bool leaveMulticastGroup(const QHostAddress &groupAddress, |
132 | const QNetworkInterface &iface) override; |
133 | QNetworkInterface multicastInterface() const override; |
134 | bool setMulticastInterface(const QNetworkInterface &iface) override; |
135 | #endif |
136 | |
137 | bool hasPendingDatagrams() const override; |
138 | qint64 pendingDatagramSize() const override; |
139 | #endif // QT_NO_UDPSOCKET |
140 | |
141 | qint64 (char *data, qint64 maxlen, QIpPacketHeader * = nullptr, |
142 | PacketHeaderOptions = WantNone) override; |
143 | qint64 (const char *data, qint64 len, const QIpPacketHeader &) override; |
144 | qint64 bytesToWrite() const override; |
145 | |
146 | #if 0 // currently unused |
147 | qint64 receiveBufferSize() const; |
148 | void setReceiveBufferSize(qint64 bufferSize); |
149 | |
150 | qint64 sendBufferSize() const; |
151 | void setSendBufferSize(qint64 bufferSize); |
152 | #endif |
153 | |
154 | int option(SocketOption option) const override; |
155 | bool setOption(SocketOption option, int value) override; |
156 | |
157 | bool waitForRead(int msecs = 30000, bool *timedOut = nullptr) override; |
158 | bool waitForWrite(int msecs = 30000, bool *timedOut = nullptr) override; |
159 | bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, |
160 | bool checkRead, bool checkWrite, |
161 | int msecs = 30000, bool *timedOut = nullptr) override; |
162 | |
163 | bool isReadNotificationEnabled() const override; |
164 | void setReadNotificationEnabled(bool enable) override; |
165 | bool isWriteNotificationEnabled() const override; |
166 | void setWriteNotificationEnabled(bool enable) override; |
167 | bool isExceptionNotificationEnabled() const override; |
168 | void setExceptionNotificationEnabled(bool enable) override; |
169 | |
170 | public Q_SLOTS: |
171 | // non-virtual override; |
172 | void connectionNotification(); |
173 | |
174 | private: |
175 | Q_DECLARE_PRIVATE(QNativeSocketEngine) |
176 | Q_DISABLE_COPY_MOVE(QNativeSocketEngine) |
177 | }; |
178 | |
179 | QT_END_NAMESPACE |
180 | |
181 | #endif // QNATIVESOCKETENGINE_P_H |
182 | |