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//#define QNATIVESOCKETENGINE_DEBUG
6
7/*! \class QNativeSocketEngine
8 \internal
9
10 \brief The QNativeSocketEngine class provides low level access to a socket.
11
12 \reentrant
13 \ingroup network
14 \inmodule QtNetwork
15
16 QtSocketLayer provides basic socket functionality provided by the
17 operating system. It also keeps track of what state the socket is
18 in, and which errors that occur.
19
20 The classes QTcpSocket, QUdpSocket and QTcpServer provide a
21 higher level API, and are in general more useful for the common
22 application.
23
24 There are two main ways of initializing the a QNativeSocketEngine; either
25 create a new socket by passing the socket type (TcpSocket or
26 UdpSocket) and network layer protocol (IPv4Protocol or
27 IPv6Protocol) to initialize(), or pass an existing socket
28 descriptor and have QNativeSocketEngine determine the type and protocol
29 itself. The native socket descriptor can later be fetched by
30 calling socketDescriptor(). The socket is made non-blocking, but
31 blocking behavior can still be achieved by calling waitForRead()
32 and waitForWrite(). isValid() can be called to check if the socket
33 has been successfully initialized and is ready to use.
34
35 To connect to a host, determine its address and pass this and the
36 port number to connectToHost(). The socket can then be used as a
37 TCP or UDP client. Otherwise; bind(), listen() and accept() are
38 used to have the socket function as a TCP or UDP server. Call
39 close() to close the socket.
40
41 bytesAvailable() is called to determine how much data is available
42 for reading. read() and write() are used by both TCP and UDP
43 clients to exchange data with the connected peer. UDP clients can
44 also call hasMoreDatagrams(), nextDatagramSize(),
45 readDatagram(), and writeDatagram().
46
47 Call state() to determine the state of the socket, for
48 example, ListeningState or ConnectedState. socketType() tells
49 whether the socket is a TCP socket or a UDP socket, or if the
50 socket type is unknown. protocol() is used to determine the
51 socket's network layer protocol.
52
53 localAddress(), localPort() are called to find the address and
54 port that are currently bound to the socket. If the socket is
55 connected, peerAddress() and peerPort() determine the address and
56 port of the connected peer.
57
58 Finally, if any function should fail, error() and
59 errorString() can be called to determine the cause of the error.
60*/
61
62/*!
63 \enum QAbstractSocketEngine::PacketHeaderOption
64
65 Specifies which fields in the IP packet header are desired in the call to
66 readDatagram().
67
68 \value WantNone caller isn't interested in the packet metadata
69 \value WantDatagramSender caller wants the sender address and port number
70 \value WantDatagramDestination caller wants the packet's destination address and port number
71 (this option is useful to distinguish multicast packets from unicast)
72 \value WantDatagramHopLimit caller wants the packet's remaining hop limit or time to live
73 (this option is useful in IPv4 multicasting, where the TTL is used
74 to indicate the realm)
75 \value WantAll this is a catch-all value to indicate the caller is
76 interested in all the available information
77
78 \sa readDatagram(), QNetworkDatagram
79*/
80
81#include "qnativesocketengine_p_p.h"
82
83#include <qabstracteventdispatcher.h>
84#include <qsocketnotifier.h>
85#include <qnetworkinterface.h>
86
87#include <private/qthread_p.h>
88#include <private/qobject_p.h>
89
90#if !defined(QT_NO_NETWORKPROXY)
91# include "qnetworkproxy.h"
92# include "qabstractsocket.h"
93# include "qtcpserver.h"
94#endif
95
96#if !defined(QT_NO_SCTP)
97# include "qsctpserver.h"
98#endif
99
100QT_BEGIN_NAMESPACE
101
102using namespace Qt::StringLiterals;
103
104//#define QNATIVESOCKETENGINE_DEBUG
105
106#define Q_VOID
107
108// Common constructs
109#define Q_CHECK_VALID_SOCKETLAYER(function, returnValue) do { \
110 if (!isValid()) { \
111 qWarning(""#function" was called on an uninitialized socket device"); \
112 return returnValue; \
113 } } while (0)
114#define Q_CHECK_INVALID_SOCKETLAYER(function, returnValue) do { \
115 if (isValid()) { \
116 qWarning(""#function" was called on an already initialized socket device"); \
117 return returnValue; \
118 } } while (0)
119#define Q_CHECK_STATE(function, checkState, returnValue) do { \
120 if (d->socketState != (checkState)) { \
121 qWarning(""#function" was not called in "#checkState); \
122 return (returnValue); \
123 } } while (0)
124#define Q_CHECK_NOT_STATE(function, checkState, returnValue) do { \
125 if (d->socketState == (checkState)) { \
126 qWarning(""#function" was called in "#checkState); \
127 return (returnValue); \
128 } } while (0)
129#define Q_CHECK_STATES(function, state1, state2, returnValue) do { \
130 if (d->socketState != (state1) && d->socketState != (state2)) { \
131 qWarning(""#function" was called" \
132 " not in "#state1" or "#state2); \
133 return (returnValue); \
134 } } while (0)
135#define Q_CHECK_STATES3(function, state1, state2, state3, returnValue) do { \
136 if (d->socketState != (state1) && d->socketState != (state2) && d->socketState != (state3)) { \
137 qWarning(""#function" was called" \
138 " not in "#state1" or "#state2); \
139 return (returnValue); \
140 } } while (0)
141#define Q_CHECK_TYPE(function, type, returnValue) do { \
142 if (d->socketType != (type)) { \
143 qWarning(#function" was called by a" \
144 " socket other than "#type""); \
145 return (returnValue); \
146 } } while (0)
147#define Q_CHECK_TYPES(function, type1, type2, returnValue) do { \
148 if (d->socketType != (type1) && d->socketType != (type2)) { \
149 qWarning(#function" was called by a" \
150 " socket other than "#type1" or "#type2); \
151 return (returnValue); \
152 } } while (0)
153#define Q_TR(a) QT_TRANSLATE_NOOP(QNativeSocketEngine, a)
154
155/*! \internal
156 Constructs the private class and initializes all data members.
157*/
158QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() :
159 socketDescriptor(-1),
160 readNotifier(nullptr),
161 writeNotifier(nullptr),
162 exceptNotifier(nullptr)
163{
164#if defined(Q_OS_WIN)
165 QSysInfo::machineHostName(); // this initializes ws2_32.dll
166#endif
167}
168
169/*! \internal
170 Destructs the private class.
171*/
172QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate()
173{
174}
175
176/*! \internal
177
178 Sets the error and error string if not set already. The only
179 interesting error is the first one that occurred, and not the last
180 one.
181*/
182void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, ErrorString errorString) const
183{
184 if (hasSetSocketError) {
185 // Only set socket errors once for one engine; expect the
186 // socket to recreate its engine after an error. Note: There's
187 // one exception: SocketError(11) bypasses this as it's purely
188 // a temporary internal error condition.
189 // Another exception is the way the waitFor*() functions set
190 // an error when a timeout occurs. After the call to setError()
191 // they reset the hasSetSocketError to false
192 return;
193 }
194 if (error != QAbstractSocket::SocketError(11))
195 hasSetSocketError = true;
196
197 socketError = error;
198
199 switch (errorString) {
200 case NonBlockingInitFailedErrorString:
201 socketErrorString = QNativeSocketEngine::tr(s: "Unable to initialize non-blocking socket");
202 break;
203 case BroadcastingInitFailedErrorString:
204 socketErrorString = QNativeSocketEngine::tr(s: "Unable to initialize broadcast socket");
205 break;
206 // should not happen anymore
207 case NoIpV6ErrorString:
208 socketErrorString = QNativeSocketEngine::tr(s: "Attempt to use IPv6 socket on a platform with no IPv6 support");
209 break;
210 case RemoteHostClosedErrorString:
211 socketErrorString = QNativeSocketEngine::tr(s: "The remote host closed the connection");
212 break;
213 case TimeOutErrorString:
214 socketErrorString = QNativeSocketEngine::tr(s: "Network operation timed out");
215 break;
216 case ResourceErrorString:
217 socketErrorString = QNativeSocketEngine::tr(s: "Out of resources");
218 break;
219 case OperationUnsupportedErrorString:
220 socketErrorString = QNativeSocketEngine::tr(s: "Unsupported socket operation");
221 break;
222 case ProtocolUnsupportedErrorString:
223 socketErrorString = QNativeSocketEngine::tr(s: "Protocol type not supported");
224 break;
225 case InvalidSocketErrorString:
226 socketErrorString = QNativeSocketEngine::tr(s: "Invalid socket descriptor");
227 break;
228 case HostUnreachableErrorString:
229 socketErrorString = QNativeSocketEngine::tr(s: "Host unreachable");
230 break;
231 case NetworkUnreachableErrorString:
232 socketErrorString = QNativeSocketEngine::tr(s: "Network unreachable");
233 break;
234 case AccessErrorString:
235 socketErrorString = QNativeSocketEngine::tr(s: "Permission denied");
236 break;
237 case ConnectionTimeOutErrorString:
238 socketErrorString = QNativeSocketEngine::tr(s: "Connection timed out");
239 break;
240 case ConnectionRefusedErrorString:
241 socketErrorString = QNativeSocketEngine::tr(s: "Connection refused");
242 break;
243 case AddressInuseErrorString:
244 socketErrorString = QNativeSocketEngine::tr(s: "The bound address is already in use");
245 break;
246 case AddressNotAvailableErrorString:
247 socketErrorString = QNativeSocketEngine::tr(s: "The address is not available");
248 break;
249 case AddressProtectedErrorString:
250 socketErrorString = QNativeSocketEngine::tr(s: "The address is protected");
251 break;
252 case DatagramTooLargeErrorString:
253 socketErrorString = QNativeSocketEngine::tr(s: "Datagram was too large to send");
254 break;
255 case SendDatagramErrorString:
256 socketErrorString = QNativeSocketEngine::tr(s: "Unable to send a message");
257 break;
258 case ReceiveDatagramErrorString:
259 socketErrorString = QNativeSocketEngine::tr(s: "Unable to receive a message");
260 break;
261 case WriteErrorString:
262 socketErrorString = QNativeSocketEngine::tr(s: "Unable to write");
263 break;
264 case ReadErrorString:
265 socketErrorString = QNativeSocketEngine::tr(s: "Network error");
266 break;
267 case PortInuseErrorString:
268 socketErrorString = QNativeSocketEngine::tr(s: "Another socket is already listening on the same port");
269 break;
270 case NotSocketErrorString:
271 socketErrorString = QNativeSocketEngine::tr(s: "Operation on non-socket");
272 break;
273 case InvalidProxyTypeString:
274 socketErrorString = QNativeSocketEngine::tr(s: "The proxy type is invalid for this operation");
275 break;
276 case TemporaryErrorString:
277 socketErrorString = QNativeSocketEngine::tr(s: "Temporary error");
278 break;
279 case NetworkDroppedConnectionErrorString:
280 socketErrorString = QNativeSocketEngine::tr(s: "Network dropped connection on reset");
281 break;
282 case ConnectionResetErrorString:
283 socketErrorString = QNativeSocketEngine::tr(s: "Connection reset by peer");
284 break;
285 case UnknownSocketErrorString:
286 socketErrorString = QNativeSocketEngine::tr(s: "Unknown error");
287 break;
288 }
289}
290
291/*!
292 \internal
293
294 Adjusts the incoming \a address family to match the currently bound address
295 (if any). This function will convert v4-mapped IPv6 addresses to IPv4 and
296 vice-versa. All other address types and values will be left unchanged.
297 */
298QHostAddress QNativeSocketEnginePrivate::adjustAddressProtocol(const QHostAddress &address) const
299{
300 QAbstractSocket::NetworkLayerProtocol targetProtocol = socketProtocol;
301 if (Q_LIKELY(targetProtocol == QAbstractSocket::UnknownNetworkLayerProtocol))
302 return address;
303
304 QAbstractSocket::NetworkLayerProtocol sourceProtocol = address.protocol();
305
306 if (targetProtocol == QAbstractSocket::AnyIPProtocol)
307 targetProtocol = QAbstractSocket::IPv6Protocol;
308 if (targetProtocol == QAbstractSocket::IPv6Protocol && sourceProtocol == QAbstractSocket::IPv4Protocol) {
309 // convert to IPv6 v4-mapped address. This always works
310 return QHostAddress(address.toIPv6Address());
311 }
312
313 if (targetProtocol == QAbstractSocket::IPv4Protocol && sourceProtocol == QAbstractSocket::IPv6Protocol) {
314 // convert to IPv4 if the source is a v4-mapped address
315 quint32 ip4 = address.toIPv4Address();
316 if (ip4)
317 return QHostAddress(ip4);
318 }
319
320 return address;
321}
322
323bool QNativeSocketEnginePrivate::checkProxy(const QHostAddress &address)
324{
325 if (address.isLoopback())
326 return true;
327
328#if !defined(QT_NO_NETWORKPROXY)
329 QObject *parent = q_func()->parent();
330 QNetworkProxy proxy;
331 QNetworkProxyQuery::QueryType queryType = QNetworkProxyQuery::TcpSocket;
332 if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(object: parent)) {
333 proxy = socket->proxy();
334 switch (socket->socketType()) {
335 case QAbstractSocket::UdpSocket:
336 queryType = QNetworkProxyQuery::UdpSocket;
337 break;
338 case QAbstractSocket::SctpSocket:
339 queryType = QNetworkProxyQuery::SctpSocket;
340 break;
341 case QAbstractSocket::TcpSocket:
342 case QAbstractSocket::UnknownSocketType:
343 queryType = QNetworkProxyQuery::TcpSocket;
344 }
345 } else if (QTcpServer *server = qobject_cast<QTcpServer *>(object: parent)) {
346 proxy = server->proxy();
347 queryType = QNetworkProxyQuery::TcpServer;
348#ifndef QT_NO_SCTP
349 if (qobject_cast<QSctpServer *>(server))
350 queryType = QNetworkProxyQuery::SctpServer;
351#endif
352 } else {
353 // no parent -> no proxy
354 return true;
355 }
356
357 if (proxy.type() == QNetworkProxy::DefaultProxy) {
358 // This is similar to what we have in QNetworkProxy::applicationProxy,
359 // the only difference is that we provide the correct query type instead of
360 // always using TcpSocket unconditionally (this is the default type for
361 // QNetworkProxyQuery).
362 QNetworkProxyQuery query;
363 query.setQueryType(queryType);
364 proxy = QNetworkProxyFactory::proxyForQuery(query).constFirst();
365 }
366
367 if (proxy.type() != QNetworkProxy::DefaultProxy &&
368 proxy.type() != QNetworkProxy::NoProxy) {
369 // QNativeSocketEngine doesn't do proxies
370 setError(error: QAbstractSocket::UnsupportedSocketOperationError,
371 errorString: QNativeSocketEnginePrivate::InvalidProxyTypeString);
372 return false;
373 }
374#endif
375
376 return true;
377}
378
379/*!
380 Constructs a QNativeSocketEngine.
381
382 \sa initialize()
383*/
384QNativeSocketEngine::QNativeSocketEngine(QObject *parent)
385 : QAbstractSocketEngine(*new QNativeSocketEnginePrivate(), parent)
386{
387}
388
389/*!
390 Destructs a QNativeSocketEngine.
391*/
392QNativeSocketEngine::~QNativeSocketEngine()
393{
394 close();
395}
396
397/*!
398 Initializes a QNativeSocketEngine by creating a new socket of type \a
399 socketType and network layer protocol \a protocol. Returns \c true on
400 success; otherwise returns \c false.
401
402 If the socket was already initialized, this function closes the
403 socket before reeinitializing it.
404
405 The new socket is non-blocking, and for UDP sockets it's also
406 broadcast enabled.
407*/
408bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol protocol)
409{
410 Q_D(QNativeSocketEngine);
411 if (isValid())
412 close();
413
414 // Create the socket
415 if (!d->createNewSocket(type: socketType, protocol)) {
416#if defined (QNATIVESOCKETENGINE_DEBUG)
417 QString typeStr = "UnknownSocketType"_L1;
418 if (socketType == QAbstractSocket::TcpSocket) typeStr = "TcpSocket"_L1;
419 else if (socketType == QAbstractSocket::UdpSocket) typeStr = "UdpSocket"_L1;
420 else if (socketType == QAbstractSocket::SctpSocket) typeStr = "SctpSocket"_L1;
421 QString protocolStr = "UnknownProtocol"_L1;
422 if (protocol == QAbstractSocket::IPv4Protocol) protocolStr = "IPv4Protocol"_L1;
423 else if (protocol == QAbstractSocket::IPv6Protocol) protocolStr = "IPv6Protocol"_L1;
424 qDebug("QNativeSocketEngine::initialize(type == %s, protocol == %s) failed: %s",
425 typeStr.toLatin1().constData(), protocolStr.toLatin1().constData(), d->socketErrorString.toLatin1().constData());
426#endif
427 return false;
428 }
429
430 if (socketType == QAbstractSocket::UdpSocket) {
431 // Set the broadcasting flag if it's a UDP socket.
432 if (!setOption(option: BroadcastSocketOption, value: 1)) {
433 d->setError(error: QAbstractSocket::UnsupportedSocketOperationError,
434 errorString: QNativeSocketEnginePrivate::BroadcastingInitFailedErrorString);
435 close();
436 return false;
437 }
438
439 // Set some extra flags that are interesting to us, but accept failure
440 setOption(option: ReceivePacketInformation, value: 1);
441 setOption(option: ReceiveHopLimit, value: 1);
442 }
443
444
445#ifndef Q_OS_WASM
446 // Make sure we receive out-of-band data
447 if (socketType == QAbstractSocket::TcpSocket
448 && !setOption(option: ReceiveOutOfBandData, value: 1)) {
449 qWarning(msg: "QNativeSocketEngine::initialize unable to inline out-of-band data");
450 }
451#endif
452
453 // Before Qt 4.6, we always set the send and receive buffer size to 49152 as
454 // this was found to be an optimal value. However, modern OS
455 // all have some kind of auto tuning for this and we therefore don't set
456 // this explicitly anymore.
457 // If it introduces any performance regressions for Qt 4.6.x (x > 0) then
458 // it will be put back in.
459 //
460 // You can use tests/manual/qhttpnetworkconnection to test HTTP download speed
461 // with this.
462 //
463 // pre-4.6:
464 // setReceiveBufferSize(49152);
465 // setSendBufferSize(49152);
466
467 return true;
468}
469
470/*! \overload
471
472 Initializes the socket using \a socketDescriptor instead of
473 creating a new one. The socket type and network layer protocol are
474 determined automatically. The socket's state is set to \a
475 socketState.
476
477 If the socket type is either TCP or UDP, it is made non-blocking.
478 UDP sockets are also broadcast enabled.
479 */
480bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState)
481{
482 Q_D(QNativeSocketEngine);
483
484 if (isValid())
485 close();
486
487 d->socketDescriptor = socketDescriptor;
488
489 // determine socket type and protocol
490 if (!d->fetchConnectionParameters()) {
491#if defined (QNATIVESOCKETENGINE_DEBUG)
492 qDebug() << "QNativeSocketEngine::initialize(socketDescriptor) failed:"
493 << socketDescriptor << d->socketErrorString;
494#endif
495 d->socketDescriptor = -1;
496 return false;
497 }
498
499 if (d->socketType != QAbstractSocket::UnknownSocketType) {
500 // Make the socket nonblocking.
501 if (!setOption(option: NonBlockingSocketOption, value: 1)) {
502 d->setError(error: QAbstractSocket::UnsupportedSocketOperationError,
503 errorString: QNativeSocketEnginePrivate::NonBlockingInitFailedErrorString);
504 close();
505 return false;
506 }
507
508 // Set the broadcasting flag if it's a UDP socket.
509 if (d->socketType == QAbstractSocket::UdpSocket
510 && !setOption(option: BroadcastSocketOption, value: 1)) {
511 d->setError(error: QAbstractSocket::UnsupportedSocketOperationError,
512 errorString: QNativeSocketEnginePrivate::BroadcastingInitFailedErrorString);
513 close();
514 return false;
515 }
516 }
517
518 d->socketState = socketState;
519 return true;
520}
521
522/*!
523 Returns \c true if the socket is valid; otherwise returns \c false. A
524 socket is valid if it has not been successfully initialized, or if
525 it has been closed.
526*/
527bool QNativeSocketEngine::isValid() const
528{
529 Q_D(const QNativeSocketEngine);
530 return d->socketDescriptor != -1;
531}
532
533/*!
534 Returns the native socket descriptor. Any use of this descriptor
535 stands the risk of being non-portable.
536*/
537qintptr QNativeSocketEngine::socketDescriptor() const
538{
539 Q_D(const QNativeSocketEngine);
540 return d->socketDescriptor;
541}
542
543/*!
544 Connects to the IP address and port specified by \a address and \a
545 port. If the connection is established, this function returns \c true
546 and the socket enters ConnectedState. Otherwise, false is
547 returned.
548
549 If false is returned, state() should be called to see if the
550 socket is in ConnectingState. If so, a delayed TCP connection is
551 taking place, and connectToHost() must be called again later to
552 determine if the connection was established successfully or
553 not. The second connection attempt must be made when the socket is
554 ready for writing. This state can be determined either by
555 connecting a QSocketNotifier to the socket descriptor returned by
556 socketDescriptor(), or by calling the blocking function
557 waitForWrite().
558
559 Example:
560 \snippet code/src_network_socket_qnativesocketengine.cpp 0
561
562 Otherwise, error() should be called to determine the cause of the
563 error.
564*/
565bool QNativeSocketEngine::connectToHost(const QHostAddress &address, quint16 port)
566{
567 Q_D(QNativeSocketEngine);
568 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::connectToHost(), false);
569
570 if (!d->checkProxy(address))
571 return false;
572
573 Q_CHECK_STATES3(QNativeSocketEngine::connectToHost(), QAbstractSocket::BoundState,
574 QAbstractSocket::UnconnectedState, QAbstractSocket::ConnectingState, false);
575
576 d->peerAddress = address;
577 d->peerPort = port;
578 bool connected = d->nativeConnect(address: d->adjustAddressProtocol(address), port);
579 if (connected)
580 d->fetchConnectionParameters();
581
582 return connected;
583}
584
585/*!
586 If there's a connection activity on the socket, process it. Then
587 notify our parent if there really was activity.
588*/
589void QNativeSocketEngine::connectionNotification()
590{
591 Q_D(QNativeSocketEngine);
592 Q_ASSERT(state() == QAbstractSocket::ConnectingState);
593
594 connectToHost(address: d->peerAddress, port: d->peerPort);
595 if (state() != QAbstractSocket::ConnectingState) {
596 // we changed states
597 QAbstractSocketEngine::connectionNotification();
598 }
599}
600
601/*!
602 Connects to the remote host name given by \a name on port \a
603 port. When this function is called, the upper-level will not
604 perform a hostname lookup.
605
606 The native socket engine does not support this operation,
607 but some other socket engines (notably proxy-based ones) do.
608*/
609bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
610{
611 Q_UNUSED(name);
612 Q_UNUSED(port);
613 Q_D(QNativeSocketEngine);
614 d->setError(error: QAbstractSocket::UnsupportedSocketOperationError,
615 errorString: QNativeSocketEnginePrivate::OperationUnsupportedErrorString);
616 return false;
617}
618
619/*!
620 Binds the socket to the address \a address and port \a
621 port. Returns \c true on success; otherwise false is returned. The
622 port may be 0, in which case an arbitrary unused port is assigned
623 automatically by the operating system.
624
625 Servers call this function to set up the server's address and
626 port. TCP servers must in addition call listen() after bind().
627*/
628bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
629{
630 Q_D(QNativeSocketEngine);
631 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bind(), false);
632
633 if (!d->checkProxy(address))
634 return false;
635
636 Q_CHECK_STATE(QNativeSocketEngine::bind(), QAbstractSocket::UnconnectedState, false);
637
638 if (!d->nativeBind(address: d->adjustAddressProtocol(address), port))
639 return false;
640
641 d->fetchConnectionParameters();
642 return true;
643}
644
645/*!
646 Prepares a TCP server for accepting incoming connections. This
647 function must be called after bind(), and only by TCP sockets.
648
649 After this function has been called, pending client connections
650 are detected by checking if the socket is ready for reading. This
651 can be done by either creating a QSocketNotifier, passing the
652 socket descriptor returned by socketDescriptor(), or by calling
653 the blocking function waitForRead().
654
655 Example:
656 \snippet code/src_network_socket_qnativesocketengine.cpp 1
657
658 \sa bind(), accept()
659*/
660bool QNativeSocketEngine::listen(int backlog)
661{
662 Q_D(QNativeSocketEngine);
663 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::listen(), false);
664 Q_CHECK_STATE(QNativeSocketEngine::listen(), QAbstractSocket::BoundState, false);
665#ifndef QT_NO_SCTP
666 Q_CHECK_TYPES(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket,
667 QAbstractSocket::SctpSocket, false);
668#else
669 Q_CHECK_TYPE(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket, false);
670#endif
671
672 return d->nativeListen(backlog);
673}
674
675/*!
676 Accepts a pending connection from the socket, which must be in
677 ListeningState, and returns its socket descriptor. If no pending
678 connections are available, -1 is returned.
679
680 \sa bind(), listen()
681*/
682qintptr QNativeSocketEngine::accept()
683{
684 Q_D(QNativeSocketEngine);
685 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::accept(), -1);
686 Q_CHECK_STATE(QNativeSocketEngine::accept(), QAbstractSocket::ListeningState, -1);
687#ifndef QT_NO_SCTP
688 Q_CHECK_TYPES(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket,
689 QAbstractSocket::SctpSocket, -1);
690#else
691 Q_CHECK_TYPE(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket, -1);
692#endif
693
694 return d->nativeAccept();
695}
696
697/*!
698 Returns the number of bytes that are currently available for
699 reading. On error, -1 is returned.
700
701 For UDP sockets, this function returns the accumulated size of all
702 pending datagrams, and it is therefore more useful for UDP sockets
703 to call hasPendingDatagrams() and pendingDatagramSize().
704*/
705qint64 QNativeSocketEngine::bytesAvailable() const
706{
707 Q_D(const QNativeSocketEngine);
708 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bytesAvailable(), -1);
709 Q_CHECK_NOT_STATE(QNativeSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, -1);
710
711 return d->nativeBytesAvailable();
712}
713
714#ifndef QT_NO_UDPSOCKET
715#ifndef QT_NO_NETWORKINTERFACE
716
717/*!
718 \since 4.8
719*/
720bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress,
721 const QNetworkInterface &iface)
722{
723 Q_D(QNativeSocketEngine);
724 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::joinMulticastGroup(), false);
725 Q_CHECK_STATE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::BoundState, false);
726 Q_CHECK_TYPE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::UdpSocket, false);
727
728 // if the user binds a socket to an IPv6 address (or QHostAddress::Any) and
729 // then attempts to join an IPv4 multicast group, this won't work on
730 // Windows. In order to make this cross-platform, we warn & fail on all
731 // platforms.
732 if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol &&
733 (d->socketProtocol == QAbstractSocket::IPv6Protocol ||
734 d->socketProtocol == QAbstractSocket::AnyIPProtocol)) {
735 qWarning(msg: "QAbstractSocket: cannot bind to QHostAddress::Any (or an IPv6 address) and join an IPv4 multicast group;"
736 " bind to QHostAddress::AnyIPv4 instead if you want to do this");
737 return false;
738 }
739
740 return d->nativeJoinMulticastGroup(groupAddress, iface);
741}
742
743/*!
744 \since 4.8
745*/
746bool QNativeSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress,
747 const QNetworkInterface &iface)
748{
749 Q_D(QNativeSocketEngine);
750 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::leaveMulticastGroup(), false);
751 Q_CHECK_STATE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::BoundState, false);
752 Q_CHECK_TYPE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::UdpSocket, false);
753 return d->nativeLeaveMulticastGroup(groupAddress, iface);
754}
755
756/*!
757 \since 4.8
758*/
759QNetworkInterface QNativeSocketEngine::multicastInterface() const
760{
761 Q_D(const QNativeSocketEngine);
762 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::multicastInterface(), QNetworkInterface());
763 Q_CHECK_TYPE(QNativeSocketEngine::multicastInterface(), QAbstractSocket::UdpSocket, QNetworkInterface());
764 return d->nativeMulticastInterface();
765}
766
767/*!
768 \since 4.8
769*/
770bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface)
771{
772 Q_D(QNativeSocketEngine);
773 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setMulticastInterface(), false);
774 Q_CHECK_TYPE(QNativeSocketEngine::setMulticastInterface(), QAbstractSocket::UdpSocket, false);
775 return d->nativeSetMulticastInterface(iface);
776}
777
778#endif // QT_NO_NETWORKINTERFACE
779
780/*!
781 Returns \c true if there is at least one datagram pending. This
782 function is only called by UDP sockets, where a datagram can have
783 a size of 0. TCP sockets call bytesAvailable().
784*/
785bool QNativeSocketEngine::hasPendingDatagrams() const
786{
787 Q_D(const QNativeSocketEngine);
788 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::hasPendingDatagrams(), false);
789 Q_CHECK_NOT_STATE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UnconnectedState, false);
790 Q_CHECK_TYPE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false);
791
792 return d->nativeHasPendingDatagrams();
793}
794
795/*!
796 Returns the size of the pending datagram, or -1 if no datagram is
797 pending. A datagram size of 0 is perfectly valid. This function is
798 called by UDP sockets before receiveMessage(). For TCP sockets,
799 call bytesAvailable().
800*/
801qint64 QNativeSocketEngine::pendingDatagramSize() const
802{
803 Q_D(const QNativeSocketEngine);
804 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::pendingDatagramSize(), -1);
805 Q_CHECK_TYPE(QNativeSocketEngine::pendingDatagramSize(), QAbstractSocket::UdpSocket, -1);
806
807 return d->nativePendingDatagramSize();
808}
809#endif // QT_NO_UDPSOCKET
810
811/*!
812 Reads up to \a maxSize bytes of a datagram from the socket,
813 stores it in \a data and returns the number of bytes read. The
814 address, port, and other IP header fields are stored in \a header
815 according to the request in \a options.
816
817 For UDP sockets, to avoid unnecessarily loss of data, call
818 pendingDatagramSize() to determine the size of the pending message
819 before reading it. If \a maxSize is too small, the rest of the
820 datagram will be lost.
821
822 Returns -1 if an error occurred.
823
824 \sa hasPendingDatagrams()
825*/
826qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxSize, QIpPacketHeader *header,
827 PacketHeaderOptions options)
828{
829 Q_D(QNativeSocketEngine);
830 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::readDatagram(), -1);
831 Q_CHECK_STATES(QNativeSocketEngine::readDatagram(), QAbstractSocket::BoundState,
832 QAbstractSocket::ConnectedState, -1);
833
834 return d->nativeReceiveDatagram(data, maxLength: maxSize, header, options);
835}
836
837/*!
838 Writes a datagram of size \a size bytes to the socket from
839 \a data to the destination contained in \a header, and returns the
840 number of bytes written, or -1 if an error occurred. If \a header
841 contains other settings like hop limit or source address, this function
842 will try to pass them to the operating system too, but will not
843 indicate an error if it could not pass them.
844
845 Only one datagram is sent, and if there is too much data to fit
846 into a single datagram, the operation will fail and error()
847 will return QAbstractSocket::DatagramTooLargeError. Operating systems impose an
848 upper limit to the size of a datagram, but this size is different
849 on almost all platforms. Sending large datagrams is in general
850 disadvised, as even if they are sent successfully, they are likely
851 to be fragmented before arriving at their destination.
852
853 Experience has shown that it is in general safe to send IPv4 datagrams
854 no larger than 512 bytes or IPv6 datagrams no larger than 1280 (the
855 minimum MTU).
856
857 \sa readDatagram()
858*/
859qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 size, const QIpPacketHeader &header)
860{
861 Q_D(QNativeSocketEngine);
862 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1);
863 Q_CHECK_STATES(QNativeSocketEngine::writeDatagram(), QAbstractSocket::BoundState,
864 QAbstractSocket::ConnectedState, -1);
865
866 return d->nativeSendDatagram(data, length: size, header);
867}
868
869/*!
870 Writes a block of \a size bytes from \a data to the socket.
871 Returns the number of bytes written, or -1 if an error occurred.
872
873 Passing zero as the \a size parameter on a connected UDP socket
874 will send an empty datagram. For other socket types results are
875 unspecified.
876*/
877qint64 QNativeSocketEngine::write(const char *data, qint64 size)
878{
879 Q_D(QNativeSocketEngine);
880 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::write(), -1);
881 Q_CHECK_STATE(QNativeSocketEngine::write(), QAbstractSocket::ConnectedState, -1);
882 return d->nativeWrite(data, length: size);
883}
884
885
886qint64 QNativeSocketEngine::bytesToWrite() const
887{
888 return 0;
889}
890
891/*!
892 Reads up to \a maxSize bytes into \a data from the socket.
893 Returns the number of bytes read, or -1 if an error occurred.
894*/
895qint64 QNativeSocketEngine::read(char *data, qint64 maxSize)
896{
897 Q_D(QNativeSocketEngine);
898 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::read(), -1);
899 Q_CHECK_STATES(QNativeSocketEngine::read(), QAbstractSocket::ConnectedState, QAbstractSocket::BoundState, -1);
900
901 qint64 readBytes = d->nativeRead(data, maxLength: maxSize);
902
903 // Handle remote close
904 if (readBytes == 0 && (d->socketType == QAbstractSocket::TcpSocket
905#ifndef QT_NO_SCTP
906 || d->socketType == QAbstractSocket::SctpSocket
907#endif
908 )) {
909 d->setError(error: QAbstractSocket::RemoteHostClosedError,
910 errorString: QNativeSocketEnginePrivate::RemoteHostClosedErrorString);
911 close();
912 return -1;
913 } else if (readBytes == -1) {
914 if (!d->hasSetSocketError) {
915 d->hasSetSocketError = true;
916 d->socketError = QAbstractSocket::NetworkError;
917 d->socketErrorString = qt_error_string();
918 }
919 close();
920 return -1;
921 }
922 return readBytes;
923}
924
925/*!
926 Closes the socket. In order to use the socket again, initialize()
927 must be called.
928*/
929void QNativeSocketEngine::close()
930{
931 Q_D(QNativeSocketEngine);
932 if (d->readNotifier)
933 d->readNotifier->setEnabled(false);
934 if (d->writeNotifier)
935 d->writeNotifier->setEnabled(false);
936 if (d->exceptNotifier)
937 d->exceptNotifier->setEnabled(false);
938
939 if (d->socketDescriptor != -1) {
940 d->nativeClose();
941 d->socketDescriptor = -1;
942 }
943 d->socketState = QAbstractSocket::UnconnectedState;
944 d->hasSetSocketError = false;
945 d->localPort = 0;
946 d->localAddress.clear();
947 d->peerPort = 0;
948 d->peerAddress.clear();
949 d->inboundStreamCount = d->outboundStreamCount = 0;
950 if (d->readNotifier) {
951 qDeleteInEventHandler(o: d->readNotifier);
952 d->readNotifier = nullptr;
953 }
954 if (d->writeNotifier) {
955 qDeleteInEventHandler(o: d->writeNotifier);
956 d->writeNotifier = nullptr;
957 }
958 if (d->exceptNotifier) {
959 qDeleteInEventHandler(o: d->exceptNotifier);
960 d->exceptNotifier = nullptr;
961 }
962}
963
964/*!
965 Waits for \a msecs milliseconds or until the socket is ready for
966 reading. If \a timedOut is not \nullptr and \a msecs milliseconds
967 have passed, the value of \a timedOut is set to true.
968
969 Returns \c true if data is available for reading; otherwise returns
970 false.
971
972 This is a blocking function call; its use is disadvised in a
973 single threaded application, as the whole thread will stop
974 responding until the function returns. waitForRead() is most
975 useful when there is no event loop available. The general approach
976 is to create a QSocketNotifier, passing the socket descriptor
977 returned by socketDescriptor() to its constructor.
978*/
979bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
980{
981 Q_D(const QNativeSocketEngine);
982 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForRead(), false);
983 Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForRead(),
984 QAbstractSocket::UnconnectedState, false);
985
986 if (timedOut)
987 *timedOut = false;
988
989 int ret = d->nativeSelect(timeout: msecs, selectForRead: true);
990 if (ret == 0) {
991 if (timedOut)
992 *timedOut = true;
993 d->setError(error: QAbstractSocket::SocketTimeoutError,
994 errorString: QNativeSocketEnginePrivate::TimeOutErrorString);
995 d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions
996 return false;
997 } else if (state() == QAbstractSocket::ConnectingState) {
998 connectToHost(address: d->peerAddress, port: d->peerPort);
999 }
1000
1001 return ret > 0;
1002}
1003
1004/*!
1005 Waits for \a msecs milliseconds or until the socket is ready for
1006 writing. If \a timedOut is not \nullptr and \a msecs milliseconds
1007 have passed, the value of \a timedOut is set to true.
1008
1009 Returns \c true if data is available for writing; otherwise returns
1010 false.
1011
1012 This is a blocking function call; its use is disadvised in a
1013 single threaded application, as the whole thread will stop
1014 responding until the function returns. waitForWrite() is most
1015 useful when there is no event loop available. The general approach
1016 is to create a QSocketNotifier, passing the socket descriptor
1017 returned by socketDescriptor() to its constructor.
1018*/
1019bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut)
1020{
1021 Q_D(QNativeSocketEngine);
1022 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForWrite(), false);
1023 Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForWrite(),
1024 QAbstractSocket::UnconnectedState, false);
1025
1026 if (timedOut)
1027 *timedOut = false;
1028
1029 int ret = d->nativeSelect(timeout: msecs, selectForRead: false);
1030 // On Windows, the socket is in connected state if a call to
1031 // select(writable) is successful. In this case we should not
1032 // issue a second call to WSAConnect()
1033#if defined (Q_OS_WIN)
1034 if (state() == QAbstractSocket::ConnectingState) {
1035 if (ret > 0) {
1036 setState(QAbstractSocket::ConnectedState);
1037 d_func()->fetchConnectionParameters();
1038 return true;
1039 } else {
1040 int value = 0;
1041 int valueSize = sizeof(value);
1042 if (::getsockopt(d->socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
1043 if (value == WSAECONNREFUSED) {
1044 d->setError(QAbstractSocket::ConnectionRefusedError, QNativeSocketEnginePrivate::ConnectionRefusedErrorString);
1045 d->socketState = QAbstractSocket::UnconnectedState;
1046 return false;
1047 } else if (value == WSAETIMEDOUT) {
1048 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::ConnectionTimeOutErrorString);
1049 d->socketState = QAbstractSocket::UnconnectedState;
1050 return false;
1051 } else if (value == WSAEHOSTUNREACH) {
1052 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::HostUnreachableErrorString);
1053 d->socketState = QAbstractSocket::UnconnectedState;
1054 return false;
1055 }
1056 }
1057 }
1058 }
1059#endif
1060
1061 if (ret == 0) {
1062 if (timedOut)
1063 *timedOut = true;
1064 d->setError(error: QAbstractSocket::SocketTimeoutError,
1065 errorString: QNativeSocketEnginePrivate::TimeOutErrorString);
1066 d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions
1067 return false;
1068 } else if (state() == QAbstractSocket::ConnectingState || (state() == QAbstractSocket::BoundState && d->socketDescriptor != -1)) {
1069 connectToHost(address: d->peerAddress, port: d->peerPort);
1070 }
1071
1072 return ret > 0;
1073}
1074
1075bool QNativeSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
1076 bool checkRead, bool checkWrite,
1077 int msecs, bool *timedOut)
1078{
1079 Q_D(QNativeSocketEngine);
1080 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForReadOrWrite(), false);
1081 Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForReadOrWrite(),
1082 QAbstractSocket::UnconnectedState, false);
1083
1084 int ret = d->nativeSelect(timeout: msecs, checkRead, checkWrite, selectForRead: readyToRead, selectForWrite: readyToWrite);
1085 // On Windows, the socket is in connected state if a call to
1086 // select(writable) is successful. In this case we should not
1087 // issue a second call to WSAConnect()
1088#if defined (Q_OS_WIN)
1089 if (state() == QAbstractSocket::ConnectingState) {
1090 if (checkWrite && ((readyToWrite && *readyToWrite) || !readyToWrite) && ret > 0) {
1091 setState(QAbstractSocket::ConnectedState);
1092 d_func()->fetchConnectionParameters();
1093 return true;
1094 } else {
1095 int value = 0;
1096 int valueSize = sizeof(value);
1097 if (::getsockopt(d->socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
1098 if (value == WSAECONNREFUSED) {
1099 d->setError(QAbstractSocket::ConnectionRefusedError, QNativeSocketEnginePrivate::ConnectionRefusedErrorString);
1100 d->socketState = QAbstractSocket::UnconnectedState;
1101 return false;
1102 } else if (value == WSAETIMEDOUT) {
1103 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::ConnectionTimeOutErrorString);
1104 d->socketState = QAbstractSocket::UnconnectedState;
1105 return false;
1106 } else if (value == WSAEHOSTUNREACH) {
1107 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::HostUnreachableErrorString);
1108 d->socketState = QAbstractSocket::UnconnectedState;
1109 return false;
1110 }
1111 }
1112 }
1113 }
1114#endif
1115 if (ret == 0) {
1116 if (timedOut)
1117 *timedOut = true;
1118 d->setError(error: QAbstractSocket::SocketTimeoutError,
1119 errorString: QNativeSocketEnginePrivate::TimeOutErrorString);
1120 d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions
1121 return false;
1122 } else if (state() == QAbstractSocket::ConnectingState) {
1123 connectToHost(address: d->peerAddress, port: d->peerPort);
1124 }
1125
1126 return ret > 0;
1127}
1128
1129#if 0 // currently unused
1130/*
1131 Returns the size of the operating system's socket receive
1132 buffer. Depending on the operating system, this size may be
1133 different from what has been set earlier with
1134 setReceiveBufferSize().
1135*/
1136qint64 QNativeSocketEngine::receiveBufferSize() const
1137{
1138 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::receiveBufferSize(), -1);
1139 return option(ReceiveBufferSocketOption);
1140}
1141
1142/*
1143 Sets the size of the operating system receive buffer to \a size.
1144
1145 For clients, this should be set before connectToHost() is called;
1146 otherwise it will have no effect. For servers, it should be called
1147 before listen().
1148
1149 The operating system receive buffer size effectively limits two
1150 things: how much data can be in transit at any one moment, and how
1151 much data can be received in one iteration of the main event loop.
1152 Setting the size of the receive buffer may have an impact on the
1153 socket's performance.
1154
1155 The default value is operating system-dependent.
1156*/
1157void QNativeSocketEngine::setReceiveBufferSize(qint64 size)
1158{
1159 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setReceiveBufferSize(), Q_VOID);
1160 setOption(ReceiveBufferSocketOption, size);
1161}
1162
1163/*
1164 Returns the size of the operating system send buffer. Depending on
1165 the operating system, this size may be different from what has
1166 been set earlier with setSendBufferSize().
1167*/
1168qint64 QNativeSocketEngine::sendBufferSize() const
1169{
1170 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setSendBufferSize(), -1);
1171 return option(SendBufferSocketOption);
1172}
1173
1174/*
1175 Sets the size of the operating system send buffer to \a size.
1176
1177 The operating system send buffer size effectively limits how much
1178 data can be in transit at any one moment. Setting the size of the
1179 send buffer may have an impact on the socket's performance.
1180
1181 The default value is operating system-dependent.
1182*/
1183void QNativeSocketEngine::setSendBufferSize(qint64 size)
1184{
1185 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setSendBufferSize(), Q_VOID);
1186 setOption(SendBufferSocketOption, size);
1187}
1188#endif
1189
1190/*!
1191 Sets the option \a option to the value \a value.
1192*/
1193bool QNativeSocketEngine::setOption(SocketOption option, int value)
1194{
1195 Q_D(QNativeSocketEngine);
1196 return d->setOption(option, value);
1197}
1198
1199/*!
1200 Returns the value of the option \a socketOption.
1201*/
1202int QNativeSocketEngine::option(SocketOption socketOption) const
1203{
1204 Q_D(const QNativeSocketEngine);
1205 return d->option(option: socketOption);
1206}
1207
1208bool QNativeSocketEngine::isReadNotificationEnabled() const
1209{
1210 Q_D(const QNativeSocketEngine);
1211 return d->readNotifier && d->readNotifier->isEnabled();
1212}
1213
1214/*
1215 \internal
1216 \class QReadNotifier
1217 \brief The QReadNotifer class is used to improve performance.
1218
1219 QReadNotifier is a private class used for performance reasons vs
1220 connecting to the QSocketNotifier activated() signal.
1221 */
1222class QReadNotifier : public QSocketNotifier
1223{
1224public:
1225 QReadNotifier(qintptr fd, QNativeSocketEngine *parent)
1226 : QSocketNotifier(fd, QSocketNotifier::Read, parent)
1227 { engine = parent; }
1228
1229protected:
1230 bool event(QEvent *) override;
1231
1232 QNativeSocketEngine *engine;
1233};
1234
1235bool QReadNotifier::event(QEvent *e)
1236{
1237 if (e->type() == QEvent::SockAct) {
1238 engine->readNotification();
1239 return true;
1240 } else if (e->type() == QEvent::SockClose) {
1241 engine->closeNotification();
1242 return true;
1243 }
1244 return QSocketNotifier::event(e);
1245}
1246
1247/*
1248 \internal
1249 \class QWriteNotifier
1250 \brief The QWriteNotifer class is used to improve performance.
1251
1252 QWriteNotifier is a private class used for performance reasons vs
1253 connecting to the QSocketNotifier activated() signal.
1254 */
1255class QWriteNotifier : public QSocketNotifier
1256{
1257public:
1258 QWriteNotifier(qintptr fd, QNativeSocketEngine *parent)
1259 : QSocketNotifier(fd, QSocketNotifier::Write, parent) { engine = parent; }
1260
1261protected:
1262 bool event(QEvent *) override;
1263
1264 QNativeSocketEngine *engine;
1265};
1266
1267bool QWriteNotifier::event(QEvent *e)
1268{
1269 if (e->type() == QEvent::SockAct) {
1270 if (engine->state() == QAbstractSocket::ConnectingState)
1271 engine->connectionNotification();
1272 else
1273 engine->writeNotification();
1274 return true;
1275 }
1276 return QSocketNotifier::event(e);
1277}
1278
1279class QExceptionNotifier : public QSocketNotifier
1280{
1281public:
1282 QExceptionNotifier(qintptr fd, QNativeSocketEngine *parent)
1283 : QSocketNotifier(fd, QSocketNotifier::Exception, parent) { engine = parent; }
1284
1285protected:
1286 bool event(QEvent *) override;
1287
1288 QNativeSocketEngine *engine;
1289};
1290
1291bool QExceptionNotifier::event(QEvent *e)
1292{
1293 if (e->type() == QEvent::SockAct) {
1294 if (engine->state() == QAbstractSocket::ConnectingState)
1295 engine->connectionNotification();
1296 else
1297 engine->exceptionNotification();
1298 return true;
1299 }
1300 return QSocketNotifier::event(e);
1301}
1302
1303void QNativeSocketEngine::setReadNotificationEnabled(bool enable)
1304{
1305 Q_D(QNativeSocketEngine);
1306 if (d->readNotifier) {
1307 d->readNotifier->setEnabled(enable);
1308 } else if (enable && d->threadData.loadRelaxed()->hasEventDispatcher()) {
1309 d->readNotifier = new QReadNotifier(d->socketDescriptor, this);
1310 d->readNotifier->setEnabled(true);
1311 }
1312}
1313
1314bool QNativeSocketEngine::isWriteNotificationEnabled() const
1315{
1316 Q_D(const QNativeSocketEngine);
1317 return d->writeNotifier && d->writeNotifier->isEnabled();
1318}
1319
1320void QNativeSocketEngine::setWriteNotificationEnabled(bool enable)
1321{
1322 Q_D(QNativeSocketEngine);
1323 if (d->writeNotifier) {
1324 d->writeNotifier->setEnabled(enable);
1325 } else if (enable && d->threadData.loadRelaxed()->hasEventDispatcher()) {
1326 d->writeNotifier = new QWriteNotifier(d->socketDescriptor, this);
1327 d->writeNotifier->setEnabled(true);
1328 }
1329}
1330
1331bool QNativeSocketEngine::isExceptionNotificationEnabled() const
1332{
1333 Q_D(const QNativeSocketEngine);
1334 return d->exceptNotifier && d->exceptNotifier->isEnabled();
1335}
1336
1337void QNativeSocketEngine::setExceptionNotificationEnabled(bool enable)
1338{
1339 Q_D(QNativeSocketEngine);
1340 if (d->exceptNotifier) {
1341 d->exceptNotifier->setEnabled(enable);
1342 } else if (enable && d->threadData.loadRelaxed()->hasEventDispatcher()) {
1343 d->exceptNotifier = new QExceptionNotifier(d->socketDescriptor, this);
1344 d->exceptNotifier->setEnabled(true);
1345 }
1346}
1347
1348QT_END_NAMESPACE
1349
1350#include "moc_qnativesocketengine_p.cpp"
1351

source code of qtbase/src/network/socket/qnativesocketengine.cpp