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