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

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