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