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 if (d->nativeCheckConnection() && state() == QAbstractSocket::ConnectedState)
605 d->fetchConnectionParameters();
606
607 if (state() != QAbstractSocket::ConnectingState) {
608 // we changed states
609 QAbstractSocketEngine::connectionNotification();
610 }
611}
612
613/*!
614 Connects to the remote host name given by \a name on port \a
615 port. When this function is called, the upper-level will not
616 perform a hostname lookup.
617
618 The native socket engine does not support this operation,
619 but some other socket engines (notably proxy-based ones) do.
620*/
621bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
622{
623 Q_UNUSED(name);
624 Q_UNUSED(port);
625 Q_D(QNativeSocketEngine);
626 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
627 QNativeSocketEnginePrivate::OperationUnsupportedErrorString);
628 return false;
629}
630
631/*!
632 Binds the socket to the address \a address and port \a
633 port. Returns \c true on success; otherwise false is returned. The
634 port may be 0, in which case an arbitrary unused port is assigned
635 automatically by the operating system.
636
637 Servers call this function to set up the server's address and
638 port. TCP servers must in addition call listen() after bind().
639*/
640bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
641{
642 Q_D(QNativeSocketEngine);
643 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bind(), false);
644
645 if (!d->checkProxy(address))
646 return false;
647
648 Q_CHECK_STATE(QNativeSocketEngine::bind(), QAbstractSocket::UnconnectedState, false);
649
650 if (!d->nativeBind(d->adjustAddressProtocol(address), port))
651 return false;
652
653 d->fetchConnectionParameters();
654 return true;
655}
656
657/*!
658 Prepares a TCP server for accepting incoming connections. This
659 function must be called after bind(), and only by TCP sockets.
660
661 After this function has been called, pending client connections
662 are detected by checking if the socket is ready for reading. This
663 can be done by either creating a QSocketNotifier, passing the
664 socket descriptor returned by socketDescriptor(), or by calling
665 the blocking function waitForRead().
666
667 Example:
668 \snippet code/src_network_socket_qnativesocketengine.cpp 1
669
670 \sa bind(), accept()
671*/
672bool QNativeSocketEngine::listen(int backlog)
673{
674 Q_D(QNativeSocketEngine);
675 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::listen(), false);
676 Q_CHECK_STATE(QNativeSocketEngine::listen(), QAbstractSocket::BoundState, false);
677#ifndef QT_NO_SCTP
678 Q_CHECK_TYPES(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket,
679 QAbstractSocket::SctpSocket, false);
680#else
681 Q_CHECK_TYPE(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket, false);
682#endif
683
684 return d->nativeListen(backlog);
685}
686
687/*!
688 Accepts a pending connection from the socket, which must be in
689 ListeningState, and returns its socket descriptor. If no pending
690 connections are available, -1 is returned.
691
692 \sa bind(), listen()
693*/
694qintptr QNativeSocketEngine::accept()
695{
696 Q_D(QNativeSocketEngine);
697 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::accept(), -1);
698 Q_CHECK_STATE(QNativeSocketEngine::accept(), QAbstractSocket::ListeningState, -1);
699#ifndef QT_NO_SCTP
700 Q_CHECK_TYPES(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket,
701 QAbstractSocket::SctpSocket, -1);
702#else
703 Q_CHECK_TYPE(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket, -1);
704#endif
705
706 return d->nativeAccept();
707}
708
709/*!
710 Returns the number of bytes that are currently available for
711 reading. On error, -1 is returned.
712
713 For UDP sockets, this function returns the accumulated size of all
714 pending datagrams, and it is therefore more useful for UDP sockets
715 to call hasPendingDatagrams() and pendingDatagramSize().
716*/
717qint64 QNativeSocketEngine::bytesAvailable() const
718{
719 Q_D(const QNativeSocketEngine);
720 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bytesAvailable(), -1);
721 Q_CHECK_NOT_STATE(QNativeSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, -1);
722
723 return d->nativeBytesAvailable();
724}
725
726#ifndef QT_NO_UDPSOCKET
727#ifndef QT_NO_NETWORKINTERFACE
728
729/*!
730 \since 4.8
731*/
732bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress,
733 const QNetworkInterface &iface)
734{
735 Q_D(QNativeSocketEngine);
736 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::joinMulticastGroup(), false);
737 Q_CHECK_STATE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::BoundState, false);
738 Q_CHECK_TYPE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::UdpSocket, false);
739
740 // if the user binds a socket to an IPv6 address (or QHostAddress::Any) and
741 // then attempts to join an IPv4 multicast group, this won't work on
742 // Windows. In order to make this cross-platform, we warn & fail on all
743 // platforms.
744 if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol &&
745 (d->socketProtocol == QAbstractSocket::IPv6Protocol ||
746 d->socketProtocol == QAbstractSocket::AnyIPProtocol)) {
747 qWarning("QAbstractSocket: cannot bind to QHostAddress::Any (or an IPv6 address) and join an IPv4 multicast group;"
748 " bind to QHostAddress::AnyIPv4 instead if you want to do this");
749 return false;
750 }
751
752 return d->nativeJoinMulticastGroup(groupAddress, iface);
753}
754
755/*!
756 \since 4.8
757*/
758bool QNativeSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress,
759 const QNetworkInterface &iface)
760{
761 Q_D(QNativeSocketEngine);
762 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::leaveMulticastGroup(), false);
763 Q_CHECK_STATE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::BoundState, false);
764 Q_CHECK_TYPE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::UdpSocket, false);
765 return d->nativeLeaveMulticastGroup(groupAddress, iface);
766}
767
768/*!
769 \since 4.8
770*/
771QNetworkInterface QNativeSocketEngine::multicastInterface() const
772{
773 Q_D(const QNativeSocketEngine);
774 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::multicastInterface(), QNetworkInterface());
775 Q_CHECK_TYPE(QNativeSocketEngine::multicastInterface(), QAbstractSocket::UdpSocket, QNetworkInterface());
776 return d->nativeMulticastInterface();
777}
778
779/*!
780 \since 4.8
781*/
782bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface)
783{
784 Q_D(QNativeSocketEngine);
785 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setMulticastInterface(), false);
786 Q_CHECK_TYPE(QNativeSocketEngine::setMulticastInterface(), QAbstractSocket::UdpSocket, false);
787 return d->nativeSetMulticastInterface(iface);
788}
789
790#endif // QT_NO_NETWORKINTERFACE
791
792/*!
793 Returns \c true if there is at least one datagram pending. This
794 function is only called by UDP sockets, where a datagram can have
795 a size of 0. TCP sockets call bytesAvailable().
796*/
797bool QNativeSocketEngine::hasPendingDatagrams() const
798{
799 Q_D(const QNativeSocketEngine);
800 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::hasPendingDatagrams(), false);
801 Q_CHECK_NOT_STATE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UnconnectedState, false);
802 Q_CHECK_TYPE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false);
803
804 return d->nativeHasPendingDatagrams();
805}
806
807/*!
808 Returns the size of the pending datagram, or -1 if no datagram is
809 pending. A datagram size of 0 is perfectly valid. This function is
810 called by UDP sockets before receiveMessage(). For TCP sockets,
811 call bytesAvailable().
812*/
813qint64 QNativeSocketEngine::pendingDatagramSize() const
814{
815 Q_D(const QNativeSocketEngine);
816 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::pendingDatagramSize(), -1);
817 Q_CHECK_TYPE(QNativeSocketEngine::pendingDatagramSize(), QAbstractSocket::UdpSocket, -1);
818
819 return d->nativePendingDatagramSize();
820}
821#endif // QT_NO_UDPSOCKET
822
823/*!
824 Reads up to \a maxSize bytes of a datagram from the socket,
825 stores it in \a data and returns the number of bytes read. The
826 address, port, and other IP header fields are stored in \a header
827 according to the request in \a options.
828
829 For UDP sockets, to avoid unnecessarily loss of data, call
830 pendingDatagramSize() to determine the size of the pending message
831 before reading it. If \a maxSize is too small, the rest of the
832 datagram will be lost.
833
834 Returns -1 if an error occurred.
835
836 \sa hasPendingDatagrams()
837*/
838qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxSize, QIpPacketHeader *header,
839 PacketHeaderOptions options)
840{
841 Q_D(QNativeSocketEngine);
842 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::readDatagram(), -1);
843 Q_CHECK_STATES(QNativeSocketEngine::readDatagram(), QAbstractSocket::BoundState,
844 QAbstractSocket::ConnectedState, -1);
845
846 return d->nativeReceiveDatagram(data, maxSize, header, options);
847}
848
849/*!
850 Writes a datagram of size \a size bytes to the socket from
851 \a data to the destination contained in \a header, and returns the
852 number of bytes written, or -1 if an error occurred. If \a header
853 contains other settings like hop limit or source address, this function
854 will try to pass them to the operating system too, but will not
855 indicate an error if it could not pass them.
856
857 Only one datagram is sent, and if there is too much data to fit
858 into a single datagram, the operation will fail and error()
859 will return QAbstractSocket::DatagramTooLargeError. Operating systems impose an
860 upper limit to the size of a datagram, but this size is different
861 on almost all platforms. Sending large datagrams is in general
862 disadvised, as even if they are sent successfully, they are likely
863 to be fragmented before arriving at their destination.
864
865 Experience has shown that it is in general safe to send IPv4 datagrams
866 no larger than 512 bytes or IPv6 datagrams no larger than 1280 (the
867 minimum MTU).
868
869 \sa readDatagram()
870*/
871qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 size, const QIpPacketHeader &header)
872{
873 Q_D(QNativeSocketEngine);
874 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1);
875 Q_CHECK_STATES(QNativeSocketEngine::writeDatagram(), QAbstractSocket::BoundState,
876 QAbstractSocket::ConnectedState, -1);
877
878 return d->nativeSendDatagram(data, size, header);
879}
880
881/*!
882 Writes a block of \a size bytes from \a data to the socket.
883 Returns the number of bytes written, or -1 if an error occurred.
884
885 Passing zero as the \a size parameter on a connected UDP socket
886 will send an empty datagram. For other socket types results are
887 unspecified.
888*/
889qint64 QNativeSocketEngine::write(const char *data, qint64 size)
890{
891 Q_D(QNativeSocketEngine);
892 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::write(), -1);
893 Q_CHECK_STATE(QNativeSocketEngine::write(), QAbstractSocket::ConnectedState, -1);
894 return d->nativeWrite(data, size);
895}
896
897
898qint64 QNativeSocketEngine::bytesToWrite() const
899{
900 return 0;
901}
902
903/*!
904 Reads up to \a maxSize bytes into \a data from the socket.
905 Returns the number of bytes read, or -1 if an error occurred.
906*/
907qint64 QNativeSocketEngine::read(char *data, qint64 maxSize)
908{
909 Q_D(QNativeSocketEngine);
910 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::read(), -1);
911 Q_CHECK_STATES(QNativeSocketEngine::read(), QAbstractSocket::ConnectedState, QAbstractSocket::BoundState, -1);
912
913 qint64 readBytes = d->nativeRead(data, maxSize);
914
915 // Handle remote close.
916 // Non-datagram socket types signal the EOF state with a zero read.
917 // Note that it is perfectly fine to have a 0-byte message with datagram
918 // sockets (SOCK_DGRAM or SOCK_SEQPACKET).
919 if (readBytes == 0 && d->socketType != QAbstractSocket::UdpSocket) {
920 d->setError(QAbstractSocket::RemoteHostClosedError,
921 QNativeSocketEnginePrivate::RemoteHostClosedErrorString);
922 close();
923 return -1;
924 } else if (readBytes == -1) {
925 if (!d->hasSetSocketError) {
926 d->hasSetSocketError = true;
927 d->socketError = QAbstractSocket::NetworkError;
928 d->socketErrorString = qt_error_string();
929 }
930 close();
931 return -1;
932 }
933 return readBytes;
934}
935
936/*!
937 Closes the socket. In order to use the socket again, initialize()
938 must be called.
939*/
940void QNativeSocketEngine::close()
941{
942 Q_D(QNativeSocketEngine);
943 if (d->readNotifier)
944 d->readNotifier->setEnabled(false);
945 if (d->writeNotifier)
946 d->writeNotifier->setEnabled(false);
947 if (d->exceptNotifier)
948 d->exceptNotifier->setEnabled(false);
949
950 if (d->socketDescriptor != -1) {
951 d->nativeClose();
952 d->socketDescriptor = -1;
953 }
954 d->socketState = QAbstractSocket::UnconnectedState;
955 d->hasSetSocketError = false;
956 d->localPort = 0;
957 d->localAddress.clear();
958 d->peerPort = 0;
959 d->peerAddress.clear();
960 d->inboundStreamCount = d->outboundStreamCount = 0;
961 if (d->readNotifier) {
962 delete d->readNotifier;
963 d->readNotifier = nullptr;
964 }
965 if (d->writeNotifier) {
966 delete d->writeNotifier;
967 d->writeNotifier = nullptr;
968 }
969 if (d->exceptNotifier) {
970 delete d->exceptNotifier;
971 d->exceptNotifier = nullptr;
972 }
973}
974
975/*!
976 Waits until \a deadline has expired or until the socket is ready for
977 reading. If \a timedOut is not \nullptr and \a deadline has expired,
978 the value of \a timedOut is set to true.
979
980 Returns \c true if data is available for reading; otherwise returns
981 false.
982
983 This is a blocking function call; its use is disadvised in a
984 single threaded application, as the whole thread will stop
985 responding until the function returns. waitForRead() is most
986 useful when there is no event loop available. The general approach
987 is to create a QSocketNotifier, passing the socket descriptor
988 returned by socketDescriptor() to its constructor.
989*/
990bool QNativeSocketEngine::waitForRead(QDeadlineTimer deadline, bool *timedOut)
991{
992 Q_D(const QNativeSocketEngine);
993 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForRead(), false);
994 Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForRead(),
995 QAbstractSocket::UnconnectedState, false);
996
997 if (timedOut)
998 *timedOut = false;
999
1000 int ret = d->nativeSelect(deadline, true);
1001 if (ret == 0) {
1002 if (timedOut)
1003 *timedOut = true;
1004 d->setError(QAbstractSocket::SocketTimeoutError,
1005 QNativeSocketEnginePrivate::TimeOutErrorString);
1006 d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions
1007 return false;
1008 } else if (state() == QAbstractSocket::ConnectingState) {
1009 connectToHost(d->peerAddress, d->peerPort);
1010 }
1011
1012 return ret > 0;
1013}
1014
1015/*!
1016 Waits until \a deadline has expired or until the socket is ready for
1017 writing. If \a timedOut is not \nullptr and \a deadline has expired,
1018 the value of \a timedOut is set to true.
1019
1020 Returns \c true if data is available for writing; otherwise returns
1021 false.
1022
1023 This is a blocking function call; its use is disadvised in a
1024 single threaded application, as the whole thread will stop
1025 responding until the function returns. waitForWrite() is most
1026 useful when there is no event loop available. The general approach
1027 is to create a QSocketNotifier, passing the socket descriptor
1028 returned by socketDescriptor() to its constructor.
1029*/
1030bool QNativeSocketEngine::waitForWrite(QDeadlineTimer deadline, bool *timedOut)
1031{
1032 Q_D(QNativeSocketEngine);
1033 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForWrite(), false);
1034 Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForWrite(),
1035 QAbstractSocket::UnconnectedState, false);
1036
1037 if (timedOut)
1038 *timedOut = false;
1039
1040 int ret = d->nativeSelect(deadline, false);
1041 // On Windows, the socket is in connected state if a call to
1042 // select(writable) is successful. In this case we should not
1043 // issue a second call to WSAConnect()
1044#if defined (Q_OS_WIN)
1045 if (state() == QAbstractSocket::ConnectingState) {
1046 if (ret > 0) {
1047 setState(QAbstractSocket::ConnectedState);
1048 d_func()->fetchConnectionParameters();
1049 return true;
1050 } else {
1051 int value = 0;
1052 int valueSize = sizeof(value);
1053 if (::getsockopt(d->socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
1054 if (value == WSAECONNREFUSED) {
1055 d->setError(QAbstractSocket::ConnectionRefusedError, QNativeSocketEnginePrivate::ConnectionRefusedErrorString);
1056 d->socketState = QAbstractSocket::UnconnectedState;
1057 return false;
1058 } else if (value == WSAETIMEDOUT) {
1059 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::ConnectionTimeOutErrorString);
1060 d->socketState = QAbstractSocket::UnconnectedState;
1061 return false;
1062 } else if (value == WSAEHOSTUNREACH) {
1063 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::HostUnreachableErrorString);
1064 d->socketState = QAbstractSocket::UnconnectedState;
1065 return false;
1066 }
1067 }
1068 }
1069 }
1070#endif
1071
1072 if (ret == 0) {
1073 if (timedOut)
1074 *timedOut = true;
1075 d->setError(QAbstractSocket::SocketTimeoutError,
1076 QNativeSocketEnginePrivate::TimeOutErrorString);
1077 d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions
1078 return false;
1079 } else if (state() == QAbstractSocket::ConnectingState || (state() == QAbstractSocket::BoundState && d->socketDescriptor != -1)) {
1080 connectToHost(d->peerAddress, d->peerPort);
1081 }
1082
1083 return ret > 0;
1084}
1085
1086bool QNativeSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
1087 bool checkRead, bool checkWrite,
1088 QDeadlineTimer deadline, bool *timedOut)
1089{
1090 Q_D(QNativeSocketEngine);
1091 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForReadOrWrite(), false);
1092 Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForReadOrWrite(),
1093 QAbstractSocket::UnconnectedState, false);
1094
1095 int ret = d->nativeSelect(deadline, checkRead, checkWrite, readyToRead, readyToWrite);
1096 // On Windows, the socket is in connected state if a call to
1097 // select(writable) is successful. In this case we should not
1098 // issue a second call to WSAConnect()
1099#if defined (Q_OS_WIN)
1100 if (state() == QAbstractSocket::ConnectingState) {
1101 if (checkWrite && ((readyToWrite && *readyToWrite) || !readyToWrite) && ret > 0) {
1102 setState(QAbstractSocket::ConnectedState);
1103 d_func()->fetchConnectionParameters();
1104 return true;
1105 } else {
1106 int value = 0;
1107 int valueSize = sizeof(value);
1108 if (::getsockopt(d->socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
1109 if (value == WSAECONNREFUSED) {
1110 d->setError(QAbstractSocket::ConnectionRefusedError, QNativeSocketEnginePrivate::ConnectionRefusedErrorString);
1111 d->socketState = QAbstractSocket::UnconnectedState;
1112 return false;
1113 } else if (value == WSAETIMEDOUT) {
1114 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::ConnectionTimeOutErrorString);
1115 d->socketState = QAbstractSocket::UnconnectedState;
1116 return false;
1117 } else if (value == WSAEHOSTUNREACH) {
1118 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::HostUnreachableErrorString);
1119 d->socketState = QAbstractSocket::UnconnectedState;
1120 return false;
1121 }
1122 }
1123 }
1124 }
1125#endif
1126 if (ret == 0) {
1127 if (timedOut)
1128 *timedOut = true;
1129 d->setError(QAbstractSocket::SocketTimeoutError,
1130 QNativeSocketEnginePrivate::TimeOutErrorString);
1131 d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions
1132 return false;
1133 } else if (state() == QAbstractSocket::ConnectingState) {
1134 connectToHost(d->peerAddress, d->peerPort);
1135 }
1136
1137 return ret > 0;
1138}
1139
1140#if 0 // currently unused
1141/*
1142 Returns the size of the operating system's socket receive
1143 buffer. Depending on the operating system, this size may be
1144 different from what has been set earlier with
1145 setReceiveBufferSize().
1146*/
1147qint64 QNativeSocketEngine::receiveBufferSize() const
1148{
1149 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::receiveBufferSize(), -1);
1150 return option(ReceiveBufferSocketOption);
1151}
1152
1153/*
1154 Sets the size of the operating system receive buffer to \a size.
1155
1156 For clients, this should be set before connectToHost() is called;
1157 otherwise it will have no effect. For servers, it should be called
1158 before listen().
1159
1160 The operating system receive buffer size effectively limits two
1161 things: how much data can be in transit at any one moment, and how
1162 much data can be received in one iteration of the main event loop.
1163 Setting the size of the receive buffer may have an impact on the
1164 socket's performance.
1165
1166 The default value is operating system-dependent.
1167*/
1168void QNativeSocketEngine::setReceiveBufferSize(qint64 size)
1169{
1170 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setReceiveBufferSize(), Q_VOID);
1171 setOption(ReceiveBufferSocketOption, size);
1172}
1173
1174/*
1175 Returns the size of the operating system send buffer. Depending on
1176 the operating system, this size may be different from what has
1177 been set earlier with setSendBufferSize().
1178*/
1179qint64 QNativeSocketEngine::sendBufferSize() const
1180{
1181 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setSendBufferSize(), -1);
1182 return option(SendBufferSocketOption);
1183}
1184
1185/*
1186 Sets the size of the operating system send buffer to \a size.
1187
1188 The operating system send buffer size effectively limits how much
1189 data can be in transit at any one moment. Setting the size of the
1190 send buffer may have an impact on the socket's performance.
1191
1192 The default value is operating system-dependent.
1193*/
1194void QNativeSocketEngine::setSendBufferSize(qint64 size)
1195{
1196 Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setSendBufferSize(), Q_VOID);
1197 setOption(SendBufferSocketOption, size);
1198}
1199#endif
1200
1201/*!
1202 Sets the option \a option to the value \a value.
1203*/
1204bool QNativeSocketEngine::setOption(SocketOption option, int value)
1205{
1206 Q_D(QNativeSocketEngine);
1207 return d->setOption(option, value);
1208}
1209
1210/*!
1211 Returns the value of the option \a socketOption.
1212*/
1213int QNativeSocketEngine::option(SocketOption socketOption) const
1214{
1215 Q_D(const QNativeSocketEngine);
1216 return d->option(socketOption);
1217}
1218
1219bool QNativeSocketEngine::isReadNotificationEnabled() const
1220{
1221 Q_D(const QNativeSocketEngine);
1222 return d->readNotifier && d->readNotifier->isEnabled();
1223}
1224
1225/*
1226 \internal
1227 \class QReadNotifier
1228 \brief The QReadNotifer class is used to improve performance.
1229
1230 QReadNotifier is a private class used for performance reasons vs
1231 connecting to the QSocketNotifier activated() signal.
1232 */
1234{
1235public:
1236 QReadNotifier(qintptr fd, QNativeSocketEngine *parent)
1238 { engine = parent; }
1239
1240protected:
1241 bool event(QEvent *) override;
1242
1244};
1245
1246bool QReadNotifier::event(QEvent *e)
1247{
1248 if (e->type() == QEvent::SockAct) {
1249 engine->readNotification();
1250 return true;
1251 } else if (e->type() == QEvent::SockClose) {
1252 engine->closeNotification();
1253 return true;
1254 }
1255 return QSocketNotifier::event(e);
1256}
1257
1258/*
1259 \internal
1260 \class QWriteNotifier
1261 \brief The QWriteNotifer class is used to improve performance.
1262
1263 QWriteNotifier is a private class used for performance reasons vs
1264 connecting to the QSocketNotifier activated() signal.
1265 */
1267{
1268public:
1269 QWriteNotifier(qintptr fd, QNativeSocketEngine *parent)
1270 : QSocketNotifier(fd, QSocketNotifier::Write, parent) { engine = parent; }
1271
1272protected:
1273 bool event(QEvent *) override;
1274
1276};
1277
1278bool QWriteNotifier::event(QEvent *e)
1279{
1280 if (e->type() == QEvent::SockAct) {
1281 if (engine->state() == QAbstractSocket::ConnectingState)
1282 engine->connectionNotification();
1283 else
1284 engine->writeNotification();
1285 return true;
1286 }
1287 return QSocketNotifier::event(e);
1288}
1289
1291{
1292public:
1293 QExceptionNotifier(qintptr fd, QNativeSocketEngine *parent)
1294 : QSocketNotifier(fd, QSocketNotifier::Exception, parent) { engine = parent; }
1295
1296protected:
1297 bool event(QEvent *) override;
1298
1300};
1301
1303{
1304 if (e->type() == QEvent::SockAct) {
1305 if (engine->state() == QAbstractSocket::ConnectingState)
1306 engine->connectionNotification();
1307 else
1308 engine->exceptionNotification();
1309 return true;
1310 }
1311 return QSocketNotifier::event(e);
1312}
1313
1314void QNativeSocketEngine::setReadNotificationEnabled(bool enable)
1315{
1316 Q_D(QNativeSocketEngine);
1317 if (d->readNotifier) {
1318 d->readNotifier->setEnabled(enable);
1319 } else if (enable && d->threadData.loadRelaxed()->hasEventDispatcher()) {
1320 d->readNotifier = new QReadNotifier(d->socketDescriptor, this);
1321 d->readNotifier->setEnabled(true);
1322 }
1323}
1324
1325bool QNativeSocketEngine::isWriteNotificationEnabled() const
1326{
1327 Q_D(const QNativeSocketEngine);
1328 return d->writeNotifier && d->writeNotifier->isEnabled();
1329}
1330
1331void QNativeSocketEngine::setWriteNotificationEnabled(bool enable)
1332{
1333 Q_D(QNativeSocketEngine);
1334 if (d->writeNotifier) {
1335 d->writeNotifier->setEnabled(enable);
1336 } else if (enable && d->threadData.loadRelaxed()->hasEventDispatcher()) {
1337 d->writeNotifier = new QWriteNotifier(d->socketDescriptor, this);
1338 d->writeNotifier->setEnabled(true);
1339 }
1340}
1341
1342bool QNativeSocketEngine::isExceptionNotificationEnabled() const
1343{
1344 Q_D(const QNativeSocketEngine);
1345 return d->exceptNotifier && d->exceptNotifier->isEnabled();
1346}
1347
1348void QNativeSocketEngine::setExceptionNotificationEnabled(bool enable)
1349{
1350 Q_D(QNativeSocketEngine);
1351 if (d->exceptNotifier) {
1352 d->exceptNotifier->setEnabled(enable);
1353 } else if (enable && d->threadData.loadRelaxed()->hasEventDispatcher()) {
1354 d->exceptNotifier = new QExceptionNotifier(d->socketDescriptor, this);
1355 d->exceptNotifier->setEnabled(true);
1356 }
1357}
1358
1359QT_END_NAMESPACE
1360
1361#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
Combined button and popup list for selecting options.
#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)