Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qabstractsocket.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5//#define QABSTRACTSOCKET_DEBUG
6
430#include <QtNetwork/private/qtnetworkglobal_p.h>
431
432#include "qabstractsocket.h"
433#include "qabstractsocket_p.h"
434
435#include "private/qhostinfo_p.h"
436
438#include <qhostaddress.h>
439#include <qhostinfo.h>
440#include <qmetaobject.h>
441#include <qpointer.h>
442#include <qtimer.h>
443#include <qdeadlinetimer.h>
444#include <qscopedvaluerollback.h>
445#include <qvarlengtharray.h>
446
447#include <private/qthread_p.h>
448
449#ifdef QABSTRACTSOCKET_DEBUG
450#include <qdebug.h>
451#include <private/qdebug_p.h>
452#endif
453
454#include <time.h>
455
456#define Q_CHECK_SOCKETENGINE(returnValue) do { \
457 if (!d->socketEngine) { \
458 return returnValue; \
459 } } while (0)
460
461#ifndef QABSTRACTSOCKET_BUFFERSIZE
462#define QABSTRACTSOCKET_BUFFERSIZE 32768
463#endif
464#define QT_TRANSFER_TIMEOUT 120000
465
467
468using namespace Qt::StringLiterals;
469using namespace std::chrono_literals;
470
473
474static constexpr auto DefaultConnectTimeout = 30s;
475
490
499
508
514{
515#if defined (QABSTRACTSOCKET_DEBUG)
516 qDebug("QAbstractSocketPrivate::resetSocketLayer()");
517#endif
518
519 hasPendingData = false;
520 if (socketEngine) {
523 delete socketEngine;
524 socketEngine = nullptr;
526 }
527 if (connectTimer)
529}
530
538{
539#ifdef QT_NO_NETWORKPROXY
540 // this is here to avoid a duplication of the call to createSocketEngine below
541 static const QNetworkProxy &proxyInUse = *(QNetworkProxy *)0;
542#endif
543
544 Q_Q(QAbstractSocket);
545#if defined (QABSTRACTSOCKET_DEBUG)
547 if (q->socketType() == QAbstractSocket::TcpSocket) typeStr = "TcpSocket"_L1;
548 else if (q->socketType() == QAbstractSocket::UdpSocket) typeStr = "UdpSocket"_L1;
549 else if (q->socketType() == QAbstractSocket::SctpSocket) typeStr = "SctpSocket"_L1;
550 else typeStr = "UnknownSocketType"_L1;
551 QString protocolStr;
552 if (protocol == QAbstractSocket::IPv4Protocol) protocolStr = "IPv4Protocol"_L1;
553 else if (protocol == QAbstractSocket::IPv6Protocol) protocolStr = "IPv6Protocol"_L1;
554 else protocolStr = "UnknownNetworkLayerProtocol"_L1;
555#endif
556
559 if (!socketEngine) {
561 QAbstractSocket::tr("Operation on socket is not supported"));
562 return false;
563 }
564 if (!socketEngine->initialize(q->socketType(), protocol)) {
565#if defined (QABSTRACTSOCKET_DEBUG)
566 qDebug("QAbstractSocketPrivate::initSocketLayer(%s, %s) failed (%s)",
567 typeStr.toLatin1().constData(), protocolStr.toLatin1().constData(),
569#endif
571 return false;
572 }
573
575
576 if (threadData.loadRelaxed()->hasEventDispatcher())
578
579#if defined (QABSTRACTSOCKET_DEBUG)
580 qDebug("QAbstractSocketPrivate::initSocketLayer(%s, %s) success",
581 typeStr.toLatin1().constData(), protocolStr.toLatin1().constData());
582#endif
583 return true;
584}
585
589{
590#ifndef QT_NO_SCTP
591 Q_Q(QAbstractSocket);
592 // Set single stream mode for unbuffered SCTP socket
595#endif
596}
597
605{
606 Q_Q(QAbstractSocket);
607#if defined (QABSTRACTSOCKET_DEBUG)
608 qDebug("QAbstractSocketPrivate::canReadNotification()");
609#endif
610
611 // If buffered, read data from the socket into the read buffer
612 if (isBuffered) {
613 const qint64 oldBufferSize = buffer.size();
614
615 // Return if there is no space in the buffer
616 if (readBufferMaxSize && oldBufferSize >= readBufferMaxSize) {
618#if defined (QABSTRACTSOCKET_DEBUG)
619 qDebug("QAbstractSocketPrivate::canReadNotification() buffer is full");
620#endif
621 return false;
622 }
623
624 // If reading from the socket fails after getting a read
625 // notification, close the socket.
626 if (!readFromSocket()) {
627#if defined (QABSTRACTSOCKET_DEBUG)
628 qDebug("QAbstractSocketPrivate::canReadNotification() disconnecting socket");
629#endif
630 q->disconnectFromHost();
631 return false;
632 }
633
634 // Return if there is no new data available.
635 if (buffer.size() == oldBufferSize) {
636 // If the socket is opened only for writing, return true
637 // to indicate that the data was discarded.
638 return !q->isReadable();
639 }
640 } else {
641 const bool isUdpSocket = (socketType == QAbstractSocket::UdpSocket);
642 if (hasPendingData && (!isUdpSocket || hasPendingDatagram)) {
644 return true;
645 }
646 if (!isUdpSocket
647#if QT_CONFIG(udpsocket)
649#endif
650 ) {
651 hasPendingData = true;
652 hasPendingDatagram = isUdpSocket;
653 }
654 }
655
657
658#if defined (QABSTRACTSOCKET_DEBUG)
659 // If we were closed as a result of the readyRead() signal.
661 qDebug("QAbstractSocketPrivate::canReadNotification() socket is closing - returning");
662#endif
663
664 return true;
665}
666
673{
674 Q_Q(QAbstractSocket);
675 // Note that this method is only called on Windows. Other platforms close in the canReadNotification()
676
677#if defined (QABSTRACTSOCKET_DEBUG)
678 qDebug("QAbstractSocketPrivate::canCloseNotification()");
679#endif
680
681 qint64 newBytes = 0;
682 if (isBuffered) {
683 // Try to read to the buffer, if the read fail we can close the socket.
684 newBytes = buffer.size();
685 qint64 oldReadBufferMaxSize = readBufferMaxSize;
686 readBufferMaxSize = 0; // temporarily disable max read buffer, we want to empty the OS buffer
687 bool hadReadFromSocket = readFromSocket();
688 readBufferMaxSize = oldReadBufferMaxSize;
689 if (!hadReadFromSocket) {
690 q->disconnectFromHost();
691 return;
692 }
693 newBytes = buffer.size() - newBytes;
694 if (newBytes) {
695 // If there was still some data to be read from the socket
696 // then we could get another FD_READ. The disconnect will
697 // then occur when we read from the socket again and fail
698 // in canReadNotification or by the manually created
699 // closeNotification below.
701
703 }
704 } else if ((socketType == QAbstractSocket::TcpSocket ||
707 }
708}
709
710
717{
718#if defined (QABSTRACTSOCKET_DEBUG)
719 qDebug("QAbstractSocketPrivate::canWriteNotification() flushing");
720#endif
721
722 return writeToSocket();
723}
724
731{
732 // If in connecting state, check if the connection has been
733 // established, otherwise flush pending data.
735#if defined (QABSTRACTSOCKET_DEBUG)
736 qDebug("QAbstractSocketPrivate::connectionNotification() testing connection");
737#endif
739 }
740}
741
752{
753 Q_Q(QAbstractSocket);
754 if (!socketEngine || !socketEngine->isValid() || (writeBuffer.isEmpty()
755 && socketEngine->bytesToWrite() == 0)) {
756#if defined (QABSTRACTSOCKET_DEBUG)
757 qDebug("QAbstractSocketPrivate::writeToSocket() nothing to do: valid ? %s, writeBuffer.isEmpty() ? %s",
758 (socketEngine && socketEngine->isValid()) ? "yes" : "no", writeBuffer.isEmpty() ? "yes" : "no");
759#endif
760
761 // this covers the case when the buffer was empty, but we had to wait for the socket engine to finish
763 q->disconnectFromHost();
764 } else {
765 if (socketEngine)
767 }
768
769 return false;
770 }
771
772 qint64 nextSize = writeBuffer.nextDataBlockSize();
773 const char *ptr = writeBuffer.readPointer();
774
775 // Attempt to write it all in one chunk.
776 qint64 written = nextSize ? socketEngine->write(ptr, nextSize) : Q_INT64_C(0);
777 if (written < 0) {
778#if defined (QABSTRACTSOCKET_DEBUG)
779 qDebug() << "QAbstractSocketPrivate::writeToSocket() write error, aborting."
781#endif
783 // an unexpected error so close the socket.
784 q->abort();
785 return false;
786 }
787
788#if defined (QABSTRACTSOCKET_DEBUG)
789 qDebug("QAbstractSocketPrivate::writeToSocket() %lld bytes written to the network",
790 written);
791#endif
792
793 if (written > 0) {
794 // Remove what we wrote so far.
795 writeBuffer.free(written);
796
797 // Emit notifications.
798 emitBytesWritten(written);
799 }
800
801 if (writeBuffer.isEmpty() && socketEngine && !socketEngine->bytesToWrite())
804 q->disconnectFromHost();
805
806 return written > 0;
807}
808
816{
817 bool dataWasWritten = false;
818
819 while (!allWriteBuffersEmpty() && writeToSocket())
820 dataWasWritten = true;
821
822 return dataWasWritten;
823}
824
825#ifndef QT_NO_NETWORKPROXY
831{
832 QList<QNetworkProxy> proxies;
833
835 // a non-default proxy was set with setProxy
836 proxies << proxy;
837 } else {
838 // try the application settings instead
846 }
847
848 // return the first that we can use
849 for (const QNetworkProxy &p : std::as_const(proxies)) {
851 (p.capabilities() & QNetworkProxy::UdpTunnelingCapability) == 0)
852 continue;
853
855 (p.capabilities() & QNetworkProxy::TunnelingCapability) == 0)
856 continue;
857
859 (p.capabilities() & QNetworkProxy::SctpTunnelingCapability) == 0)
860 continue;
861
862 proxyInUse = p;
863 return;
864 }
865
866 // no proxy found
867 // DefaultProxy here will raise an error
869}
870#endif // !QT_NO_NETWORKPROXY
871
872#if !defined(QT_NO_NETWORKPROXY)
880{
881 Q_Q(QAbstractSocket);
883 return;
884
885#if defined(QABSTRACTSOCKET_DEBUG)
886 qDebug("QAbstractSocketPrivate::startConnectingByName(host == %s)", qPrintable(host));
887#endif
888
889 // ### Let the socket engine drive this?
891 emit q->stateChanged(state);
892
894 // Try to connect to the host. If it succeeds immediately
895 // (e.g. QSocks5SocketEngine in UDPASSOCIATE mode), emit
896 // connected() and return.
899 return;
900 }
901
903 return;
904
905 // failed to connect
907 }
908
910 emit q->errorOccurred(socketError);
911 emit q->stateChanged(state);
912}
913
914#endif // !QT_NO_NETWORKPROXY
915
924{
925 Q_Q(QAbstractSocket);
928 return;
929
930 if (hostLookupId != -1 && hostLookupId != hostInfo.lookupId()) {
931 qWarning("QAbstractSocketPrivate::_q_startConnecting() received hostInfo for wrong lookup ID %d expected %d", hostInfo.lookupId(), hostLookupId);
932 }
933
934 // Only add the addresses for the preferred network layer.
935 // Or all if preferred network layer is not set.
937 addresses = hostInfo.addresses();
938 } else {
939 const auto candidates = hostInfo.addresses();
940 for (const QHostAddress &address : candidates) {
941 if (address.protocol() == preferredNetworkLayerProtocol)
943 }
944 }
945
946
947#if defined(QABSTRACTSOCKET_DEBUG)
948 QString s = "{"_L1;
949 for (int i = 0; i < addresses.count(); ++i) {
950 if (i != 0) s += ", "_L1;
951 s += addresses.at(i).toString();
952 }
953 s += u'}';
954 qDebug("QAbstractSocketPrivate::_q_startConnecting(hostInfo == %s)", s.toLatin1().constData());
955#endif
956
957 // Try all addresses twice.
959
960 // If there are no addresses in the host list, report this to the
961 // user.
962 if (addresses.isEmpty()) {
963#if defined(QABSTRACTSOCKET_DEBUG)
964 qDebug("QAbstractSocketPrivate::_q_startConnecting(), host not found");
965#endif
967 setError(QAbstractSocket::HostNotFoundError, QAbstractSocket::tr("Host not found"));
968 emit q->stateChanged(state);
970 return;
971 }
972
973 // Enter Connecting state (see also sn_write, which is called by
974 // the write socket notifier after connect())
976 emit q->stateChanged(state);
977
978 // Report the successful host lookup
979 emit q->hostFound();
980
981 // The addresses returned by the lookup will be tested one after
982 // another by _q_connectToNextAddress().
984}
985
996{
997 Q_Q(QAbstractSocket);
998 do {
999 // Check for more pending addresses
1000 if (addresses.isEmpty()) {
1001#if defined(QABSTRACTSOCKET_DEBUG)
1002 qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), all addresses failed.");
1003#endif
1005 if (socketEngine) {
1007#ifdef Q_OS_AIX
1008 // On AIX, the second connect call will result in EINVAL and not
1009 // ECONNECTIONREFUSED; although the meaning is the same.
1011#endif
1014 QAbstractSocket::tr("Connection refused"));
1015 } else {
1017 }
1018 } else {
1019// socketError = QAbstractSocket::ConnectionRefusedError;
1020// q->setErrorString(QAbstractSocket::tr("Connection refused"));
1021 }
1022 emit q->stateChanged(state);
1023 emit q->errorOccurred(socketError);
1024 return;
1025 }
1026
1027 // Pick the first host address candidate
1029#if defined(QABSTRACTSOCKET_DEBUG)
1030 qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), connecting to %s:%i, %d left to try",
1032#endif
1033
1035 // hope that the next address is better
1036#if defined(QABSTRACTSOCKET_DEBUG)
1037 qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), failed to initialize sock layer");
1038#endif
1039 continue;
1040 }
1041
1042 // Tries to connect to the address. If it succeeds immediately
1043 // (localhost address on BSD or any UDP connect), emit
1044 // connected() and return.
1045 if (
1047 //_q_testConnection();
1049 return;
1050 }
1051
1052 // Check that we're in delayed connection state. If not, try
1053 // the next address
1055#if defined(QABSTRACTSOCKET_DEBUG)
1056 qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), connection failed (%s)",
1058#endif
1059 continue;
1060 }
1061
1062 // Start the connect timer.
1063 if (threadData.loadRelaxed()->hasEventDispatcher()) {
1064 if (!connectTimer) {
1065 connectTimer = new QTimer(q);
1069 }
1071 }
1072
1073 // Wait for a write notification that will eventually call
1074 // _q_testConnection().
1076 break;
1078}
1079
1086{
1087 if (connectTimer)
1088 connectTimer->stop();
1089
1090 if (socketEngine) {
1092 // Fetch the parameters if our connection is completed;
1093 // otherwise, fall out and try the next address.
1095 if (pendingClose) {
1096 q_func()->disconnectFromHost();
1097 pendingClose = false;
1098 }
1099 return;
1100 }
1101
1102 // don't retry the other addresses if we had a proxy error
1104 addresses.clear();
1105 }
1106
1107#if defined(QABSTRACTSOCKET_DEBUG)
1108 qDebug("QAbstractSocketPrivate::_q_testConnection() connection failed,"
1109 " checking for alternative addresses");
1110#endif
1112}
1113
1122{
1123 Q_Q(QAbstractSocket);
1124#if defined(QABSTRACTSOCKET_DEBUG)
1125 qDebug("QAbstractSocketPrivate::_q_abortConnectionAttempt() (timed out)");
1126#endif
1127 if (socketEngine)
1129
1130 connectTimer->stop();
1131
1132 if (addresses.isEmpty()) {
1135 QAbstractSocket::tr("Connection timed out"));
1136 emit q->stateChanged(state);
1137 emit q->errorOccurred(socketError);
1138 } else {
1140 }
1141}
1142
1149{
1150 Q_Q(QAbstractSocket);
1151 // Find how many bytes we can read from the socket layer.
1152 qint64 bytesToRead = socketEngine->bytesAvailable();
1153 if (bytesToRead == 0) {
1154 // Under heavy load, certain conditions can trigger read notifications
1155 // for socket notifiers on which there is no activity. If we continue
1156 // to read 0 bytes from the socket, we will trigger behavior similar
1157 // to that which signals a remote close. When we hit this condition,
1158 // we try to read 4k of data from the socket, which will give us either
1159 // an EAGAIN/EWOULDBLOCK if the connection is alive (i.e., the remote
1160 // host has _not_ disappeared).
1161 bytesToRead = 4096;
1162 }
1163
1164 if (q->isReadable()) {
1165 if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - buffer.size()))
1166 bytesToRead = readBufferMaxSize - buffer.size();
1167
1168#if defined(QABSTRACTSOCKET_DEBUG)
1169 qDebug("QAbstractSocketPrivate::readFromSocket() about to read %lld bytes",
1170 bytesToRead);
1171#endif
1172
1173 // Read from the socket, store data in the read buffer.
1174 char *ptr = buffer.reserve(bytesToRead);
1175 qint64 readBytes = socketEngine->read(ptr, bytesToRead);
1176 if (readBytes == -2) {
1177 // No bytes currently available for reading.
1178 buffer.chop(bytesToRead);
1179 return true;
1180 }
1181 buffer.chop(bytesToRead - (readBytes < 0 ? qint64(0) : readBytes));
1182#if defined(QABSTRACTSOCKET_DEBUG)
1183 qDebug("QAbstractSocketPrivate::readFromSocket() got %lld bytes, buffer size = %lld",
1184 readBytes, buffer.size());
1185#endif
1186 } else {
1187 // Discard unwanted data if opened in WriteOnly mode
1188 QVarLengthArray<char, 4096> discardBuffer(bytesToRead);
1189
1190#if defined(QABSTRACTSOCKET_DEBUG)
1191 qDebug("QAbstractSocketPrivate::readFromSocket() about to discard %lld bytes",
1192 bytesToRead);
1193#endif
1194 socketEngine->read(discardBuffer.data(), bytesToRead);
1195 }
1196
1197 if (!socketEngine->isValid()) {
1198#if defined(QABSTRACTSOCKET_DEBUG)
1199 qDebug("QAbstractSocketPrivate::readFromSocket() read failed: %s",
1201#endif
1204 return false;
1205 }
1206
1207 return true;
1208}
1209
1215{
1216 Q_Q(QAbstractSocket);
1217 // Only emit readyRead() when not recursing.
1219 QScopedValueRollback<bool> r(emittedReadyRead);
1220 emittedReadyRead = true;
1221 emit q->readyRead();
1222 }
1223 // channelReadyRead() can be emitted recursively - even for the same channel.
1224 emit q->channelReadyRead(channel);
1225}
1226
1232{
1233 Q_Q(QAbstractSocket);
1234 // Only emit bytesWritten() when not recursing.
1236 QScopedValueRollback<bool> r(emittedBytesWritten);
1237 emittedBytesWritten = true;
1238 emit q->bytesWritten(bytes);
1239 }
1240 // channelBytesWritten() can be emitted recursively - even for the same channel.
1241 emit q->channelBytesWritten(channel, bytes);
1242}
1243
1249{
1250 Q_Q(QAbstractSocket);
1251
1253 if (socketEngine) {
1254 if (q->isReadable()) {
1255 const int inboundStreamCount = socketEngine->inboundStreamCount();
1256 setReadChannelCount(qMax(1, inboundStreamCount));
1257 if (inboundStreamCount == 0)
1258 readChannelCount = 0;
1259 }
1260 if (q->isWritable()) {
1261 const int outboundStreamCount = socketEngine->outboundStreamCount();
1262 setWriteChannelCount(qMax(1, outboundStreamCount));
1263 if (outboundStreamCount == 0)
1265 }
1273 }
1274
1276#if defined(QABSTRACTSOCKET_DEBUG)
1277 qDebug("QAbstractSocketPrivate::fetchConnectionParameters() connection to %s:%i established",
1279#endif
1280 emit q->stateChanged(state);
1281 emit q->connected();
1282}
1283
1287{
1288 Q_D(const QAbstractSocket);
1289
1290 // if we're not connected, return -1 indicating EOF
1291 if (!d->socketEngine || !d->socketEngine->isValid()
1293 return -1;
1294
1295 // Caller, QIODevice::skip(), has ensured buffer is empty. So, wait
1296 // for more data in buffered mode.
1297 if (d->isBuffered)
1298 return 0;
1299
1300 return QIODevice::skipData(maxSize);
1301}
1302
1304{
1305 QAbstractSocketEngine *socketEngine = socket->d_func()->socketEngine;
1306 if (!socketEngine)
1307 return;
1311
1312#ifdef QABSTRACTSOCKET_DEBUG
1314 << "pause notifiers, storing 'true' states, currently read:" << read
1315 << "write:" << write << "except:" << except;
1316#endif
1317 // We do this if-check to avoid accidentally overwriting any previously stored state
1318 // It will reset to false once the socket is re-enabled.
1319 if (read) {
1320 socket->d_func()->prePauseReadSocketNotifierState = true;
1322 }
1323 if (write) {
1324 socket->d_func()->prePauseWriteSocketNotifierState = true;
1326 }
1327 if (except) {
1328 socket->d_func()->prePauseExceptionSocketNotifierState = true;
1330 }
1331}
1332
1334{
1335 QAbstractSocketEngine *socketEngine = socket->d_func()->socketEngine;
1336 if (!socketEngine)
1337 return;
1338 QAbstractSocketPrivate *priv = socket->d_func();
1339#ifdef QABSTRACTSOCKET_DEBUG
1341 << "Maybe resume notifiers, read:" << priv->prePauseReadSocketNotifierState
1342 << "write:" << priv->prePauseWriteSocketNotifierState
1343 << "exception:" << priv->prePauseExceptionSocketNotifierState;
1344#endif
1345 if (std::exchange(priv->prePauseReadSocketNotifierState, false))
1347 if (std::exchange(priv->prePauseWriteSocketNotifierState, false))
1349 if (std::exchange(priv->prePauseExceptionSocketNotifierState, false))
1351}
1352
1357
1364 const QString &errStr)
1365{
1366 socketError = errorCode;
1367 errorString = errStr;
1368}
1369
1377 const QString &errorString)
1378{
1379 Q_Q(QAbstractSocket);
1380 setError(errorCode, errorString);
1381 emit q->errorOccurred(errorCode);
1382}
1383
1390 QAbstractSocketPrivate &dd, QObject *parent)
1391 : QIODevice(dd, parent)
1392{
1393 Q_D(QAbstractSocket);
1394#if defined(QABSTRACTSOCKET_DEBUG)
1395 qDebug("QAbstractSocket::QAbstractSocket(%sSocket, QAbstractSocketPrivate == %p, parent == %p)",
1396 socketType == TcpSocket ? "Tcp" : socketType == UdpSocket ? "Udp"
1397 : socketType == SctpSocket ? "Sctp" : "Unknown", &dd, parent);
1398#endif
1399 d->socketType = socketType;
1400}
1401
1412
1417{
1418 Q_D(QAbstractSocket);
1419#if defined(QABSTRACTSOCKET_DEBUG)
1420 qDebug("QAbstractSocket::~QAbstractSocket()");
1421#endif
1422 if (d->state != UnconnectedState)
1423 abort();
1424}
1425
1442
1450QAbstractSocket::PauseModes QAbstractSocket::pauseMode() const
1451{
1452 return d_func()->pauseMode;
1453}
1454
1455
1470void QAbstractSocket::setPauseMode(PauseModes pauseMode)
1471{
1472 d_func()->pauseMode = pauseMode;
1473}
1474
1496{
1497 Q_D(QAbstractSocket);
1498 return d->bind(address, port, mode);
1499}
1500
1501bool QAbstractSocketPrivate::bind(const QHostAddress &address, quint16 port, QAbstractSocket::BindMode mode)
1502{
1503 Q_Q(QAbstractSocket);
1504
1505 // now check if the socket engine is initialized and to the right type
1506 if (!socketEngine || !socketEngine->isValid()) {
1507 QHostAddress nullAddress;
1508 resolveProxy(nullAddress.toString(), port);
1509
1510 QAbstractSocket::NetworkLayerProtocol protocol = address.protocol();
1512 protocol = nullAddress.protocol();
1513
1514 if (!initSocketLayer(protocol))
1515 return false;
1516 }
1517
1519#ifdef Q_OS_UNIX
1522 else
1524#endif
1525#ifdef Q_OS_WIN
1528 else
1532 else
1534#endif
1535 }
1538
1539 if (!result) {
1541 return false;
1542 }
1543
1547
1548 emit q->stateChanged(state);
1549 // A slot attached to stateChanged() signal can break our invariant:
1550 // by closing the socket it will reset its socket engine - thus we
1551 // have additional check (isValid()) ...
1552 if (q->isValid() && socketType == QAbstractSocket::UdpSocket)
1554 return true;
1555}
1556
1579#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
1580bool QAbstractSocket::bind(quint16 port, BindMode mode)
1581{
1582 return bind(QHostAddress::Any, port, mode);
1583}
1584#endif
1585
1596{
1597 return d_func()->socketEngine ? d_func()->socketEngine->isValid() : isOpen();
1598}
1599
1624 OpenMode openMode,
1625 NetworkLayerProtocol protocol)
1626{
1627 Q_D(QAbstractSocket);
1628#if defined(QABSTRACTSOCKET_DEBUG)
1629 qDebug("QAbstractSocket::connectToHost(\"%s\", %i, %i)...", qPrintable(hostName), port,
1630 (int) openMode);
1631#endif
1632
1633 if (d->state == ConnectedState || d->state == ConnectingState
1634 || d->state == ClosingState || d->state == HostLookupState) {
1635 qWarning("QAbstractSocket::connectToHost() called when already looking up or connecting/connected to \"%s\"", qPrintable(hostName));
1636 d->setErrorAndEmit(OperationError, tr("Trying to connect while connection is in progress"));
1637 return;
1638 }
1639
1640 d->preferredNetworkLayerProtocol = protocol;
1641 d->hostName = hostName;
1642 d->port = port;
1643 d->setReadChannelCount(0);
1644 d->setWriteChannelCount(0);
1645 d->abortCalled = false;
1646 d->pendingClose = false;
1647 if (d->state != BoundState) {
1648 d->state = UnconnectedState;
1649 d->localPort = 0;
1650 d->localAddress.clear();
1651 }
1652 d->peerPort = 0;
1653 d->peerAddress.clear();
1654 d->peerName = hostName;
1655 if (d->hostLookupId != -1) {
1656 QHostInfo::abortHostLookup(d->hostLookupId);
1657 d->hostLookupId = -1;
1658 }
1659
1660#ifndef QT_NO_NETWORKPROXY
1661 // Get the proxy information
1662 d->resolveProxy(hostName, port);
1663 if (d->proxyInUse.type() == QNetworkProxy::DefaultProxy) {
1664 // failed to setup the proxy
1665 d->setErrorAndEmit(UnsupportedSocketOperationError,
1666 tr("Operation on socket is not supported"));
1667 return;
1668 }
1669#endif
1670
1671 // Sync up with error string, which open() shall clear.
1672 d->socketError = UnknownSocketError;
1674 d->isBuffered = false;
1675 else if (!d_func()->isBuffered)
1677
1679 d->readChannelCount = d->writeChannelCount = 0;
1680
1681 d->state = HostLookupState;
1682 emit stateChanged(d->state);
1683
1684 QHostAddress temp;
1685 if (temp.setAddress(hostName)) {
1687 info.setAddresses(QList<QHostAddress>() << temp);
1688 d->_q_startConnecting(info);
1689#ifndef QT_NO_NETWORKPROXY
1690 } else if (d->proxyInUse.capabilities() & QNetworkProxy::HostNameLookupCapability) {
1691 // the proxy supports connection by name, so use it
1692 d->startConnectingByName(hostName);
1693 return;
1694#endif
1695 } else {
1696 if (d->threadData.loadRelaxed()->hasEventDispatcher()) {
1697 // this internal API for QHostInfo either immediately gives us the desired
1698 // QHostInfo from cache or later calls the _q_startConnecting slot.
1699 bool immediateResultValid = false;
1700 QHostInfo hostInfo = qt_qhostinfo_lookup(hostName,
1701 this,
1702 SLOT(_q_startConnecting(QHostInfo)),
1703 &immediateResultValid,
1704 &d->hostLookupId);
1705 if (immediateResultValid) {
1706 d->hostLookupId = -1;
1707 d->_q_startConnecting(hostInfo);
1708 }
1709 }
1710 }
1711
1712#if defined(QABSTRACTSOCKET_DEBUG)
1713 qDebug("QAbstractSocket::connectToHost(\"%s\", %i) == %s%s", hostName.toLatin1().constData(), port,
1714 (d->state == ConnectedState) ? "true" : "false",
1715 (d->state == ConnectingState || d->state == HostLookupState)
1716 ? " (connection in progress)" : "");
1717#endif
1718}
1719
1725 OpenMode openMode)
1726{
1727#if defined(QABSTRACTSOCKET_DEBUG)
1728 qDebug("QAbstractSocket::connectToHost([%s], %i, %i)...",
1729 address.toString().toLatin1().constData(), port, (int) openMode);
1730#endif
1731 connectToHost(address.toString(), port, openMode);
1732}
1733
1742{
1743 const qint64 pendingBytes = QIODevice::bytesToWrite();
1744#if defined(QABSTRACTSOCKET_DEBUG)
1745 qDebug("QAbstractSocket::bytesToWrite() == %lld", pendingBytes);
1746#endif
1747 return pendingBytes;
1748}
1749
1756{
1757 Q_D(const QAbstractSocket);
1758 qint64 available = QIODevice::bytesAvailable();
1759
1760 if (!d->isBuffered && d->socketEngine && d->socketEngine->isValid())
1761 available += d->socketEngine->bytesAvailable();
1762
1763#if defined(QABSTRACTSOCKET_DEBUG)
1764 qDebug("QAbstractSocket::bytesAvailable() == %lld", available);
1765#endif
1766 return available;
1767}
1768
1776{
1777 Q_D(const QAbstractSocket);
1778 return d->localPort;
1779}
1780
1792{
1793 Q_D(const QAbstractSocket);
1794 return d->localAddress;
1795}
1796
1804{
1805 Q_D(const QAbstractSocket);
1806 return d->peerPort;
1807}
1808
1816{
1817 Q_D(const QAbstractSocket);
1818 return d->peerAddress;
1819}
1820
1828{
1829 Q_D(const QAbstractSocket);
1830 return d->peerName.isEmpty() ? d->hostName : d->peerName;
1831}
1832
1846{
1847 Q_D(const QAbstractSocket);
1848 return d->cachedSocketDescriptor;
1849}
1850
1865 OpenMode openMode)
1866{
1867 Q_D(QAbstractSocket);
1868
1869 d->resetSocketLayer();
1870 d->setReadChannelCount(0);
1871 d->setWriteChannelCount(0);
1873 if (!d->socketEngine) {
1874 d->setError(UnsupportedSocketOperationError, tr("Operation on socket is not supported"));
1875 return false;
1876 }
1877 bool result = d->socketEngine->initialize(socketDescriptor, socketState);
1878 if (!result) {
1879 d->setError(d->socketEngine->error(), d->socketEngine->errorString());
1880 return false;
1881 }
1882
1883 // Sync up with error string, which open() shall clear.
1884 d->socketError = UnknownSocketError;
1885 if (d->threadData.loadRelaxed()->hasEventDispatcher())
1886 d->socketEngine->setReceiver(d);
1887
1889
1890 if (socketState == ConnectedState) {
1891 if (isReadable()) {
1892 const int inboundStreamCount = d->socketEngine->inboundStreamCount();
1893 d->setReadChannelCount(qMax(1, inboundStreamCount));
1894 if (inboundStreamCount == 0)
1895 d->readChannelCount = 0;
1896 }
1897 if (isWritable()) {
1898 const int outboundStreamCount = d->socketEngine->outboundStreamCount();
1899 d->setWriteChannelCount(qMax(1, outboundStreamCount));
1900 if (outboundStreamCount == 0)
1901 d->writeChannelCount = 0;
1902 }
1903 } else {
1904 d->readChannelCount = d->writeChannelCount = 0;
1905 }
1906
1907 if (d->state != socketState) {
1908 d->state = socketState;
1909 emit stateChanged(d->state);
1910 }
1911
1912 d->pendingClose = false;
1913 d->socketEngine->setReadNotificationEnabled(true);
1914 d->localPort = d->socketEngine->localPort();
1915 d->peerPort = d->socketEngine->peerPort();
1916 d->localAddress = d->socketEngine->localAddress();
1917 d->peerAddress = d->socketEngine->peerAddress();
1918 d->cachedSocketDescriptor = socketDescriptor;
1919
1920 return true;
1921}
1922
1934{
1935 if (!d_func()->socketEngine)
1936 return;
1937
1938 switch (option) {
1939 case LowDelayOption:
1940 d_func()->socketEngine->setOption(QAbstractSocketEngine::LowDelayOption, value.toInt());
1941 break;
1942
1943 case KeepAliveOption:
1944 d_func()->socketEngine->setOption(QAbstractSocketEngine::KeepAliveOption, value.toInt());
1945 break;
1946
1947 case MulticastTtlOption:
1948 d_func()->socketEngine->setOption(QAbstractSocketEngine::MulticastTtlOption, value.toInt());
1949 break;
1950
1952 d_func()->socketEngine->setOption(QAbstractSocketEngine::MulticastLoopbackOption, value.toInt());
1953 break;
1954
1956 d_func()->socketEngine->setOption(QAbstractSocketEngine::TypeOfServiceOption, value.toInt());
1957 break;
1958
1960 d_func()->socketEngine->setOption(QAbstractSocketEngine::SendBufferSocketOption, value.toInt());
1961 break;
1962
1964 d_func()->socketEngine->setOption(QAbstractSocketEngine::ReceiveBufferSocketOption, value.toInt());
1965 break;
1966
1968 d_func()->socketEngine->setOption(QAbstractSocketEngine::PathMtuInformation, value.toInt());
1969 break;
1970 }
1971}
1972
1980{
1981 if (!d_func()->socketEngine)
1982 return QVariant();
1983
1984 int ret = -1;
1985 switch (option) {
1986 case LowDelayOption:
1987 ret = d_func()->socketEngine->option(QAbstractSocketEngine::LowDelayOption);
1988 break;
1989
1990 case KeepAliveOption:
1991 ret = d_func()->socketEngine->option(QAbstractSocketEngine::KeepAliveOption);
1992 break;
1993
1994 case MulticastTtlOption:
1995 ret = d_func()->socketEngine->option(QAbstractSocketEngine::MulticastTtlOption);
1996 break;
1998 ret = d_func()->socketEngine->option(QAbstractSocketEngine::MulticastLoopbackOption);
1999 break;
2000
2002 ret = d_func()->socketEngine->option(QAbstractSocketEngine::TypeOfServiceOption);
2003 break;
2004
2006 ret = d_func()->socketEngine->option(QAbstractSocketEngine::SendBufferSocketOption);
2007 break;
2008
2010 ret = d_func()->socketEngine->option(QAbstractSocketEngine::ReceiveBufferSocketOption);
2011 break;
2012
2014 ret = d_func()->socketEngine->option(QAbstractSocketEngine::PathMtuInformation);
2015 break;
2016 }
2017 if (ret == -1)
2018 return QVariant();
2019 else
2020 return QVariant(ret);
2021}
2022
2049{
2050 Q_D(QAbstractSocket);
2051#if defined (QABSTRACTSOCKET_DEBUG)
2052 qDebug("QAbstractSocket::waitForConnected(%i)", msecs);
2053#endif
2054
2055 if (state() == ConnectedState) {
2056#if defined (QABSTRACTSOCKET_DEBUG)
2057 qDebug("QAbstractSocket::waitForConnected(%i) already connected", msecs);
2058#endif
2059 return true;
2060 }
2061
2062 bool wasPendingClose = d->pendingClose;
2063 d->pendingClose = false;
2064 QDeadlineTimer deadline{msecs};
2065
2066 if (d->state == HostLookupState) {
2067#if defined (QABSTRACTSOCKET_DEBUG)
2068 qDebug("QAbstractSocket::waitForConnected(%i) doing host name lookup", msecs);
2069#endif
2070 QHostInfo::abortHostLookup(d->hostLookupId);
2071 d->hostLookupId = -1;
2072 QHostAddress temp;
2073 if (temp.setAddress(d->hostName)) {
2075 info.setAddresses(QList<QHostAddress>() << temp);
2076 d->_q_startConnecting(info);
2077 } else {
2078 d->_q_startConnecting(QHostInfo::fromName(d->hostName));
2079 }
2080 }
2081 if (state() == UnconnectedState)
2082 return false; // connect not im progress anymore!
2083
2084 bool timedOut = true;
2085#if defined (QABSTRACTSOCKET_DEBUG)
2086 int attempt = 1;
2087#endif
2088 while (state() == ConnectingState && !deadline.hasExpired()) {
2092#if defined (QABSTRACTSOCKET_DEBUG)
2093 qDebug("QAbstractSocket::waitForConnected(%i) waiting %.2f secs for connection attempt #%i",
2094 msecs, timer.remainingTime() / 1000.0, attempt++);
2095#endif
2096 timedOut = false;
2097
2098 if (d->socketEngine && d->socketEngine->waitForWrite(timer, &timedOut) && !timedOut) {
2099 d->_q_testConnection();
2100 } else {
2101 d->_q_connectToNextAddress();
2102 }
2103 }
2104
2105 if ((timedOut && state() != ConnectedState) || state() == ConnectingState) {
2106 d->setError(SocketTimeoutError, tr("Socket operation timed out"));
2107 d->state = UnconnectedState;
2108 emit stateChanged(d->state);
2109 d->resetSocketLayer();
2110 }
2111
2112#if defined (QABSTRACTSOCKET_DEBUG)
2113 qDebug("QAbstractSocket::waitForConnected(%i) == %s", msecs,
2114 state() == ConnectedState ? "true" : "false");
2115#endif
2116 if (state() != ConnectedState)
2117 return false;
2118 if (wasPendingClose)
2120 return true;
2121}
2122
2139{
2140 Q_D(QAbstractSocket);
2141#if defined (QABSTRACTSOCKET_DEBUG)
2142 qDebug("QAbstractSocket::waitForReadyRead(%i)", msecs);
2143#endif
2144
2145 // require calling connectToHost() before waitForReadyRead()
2146 if (state() == UnconnectedState) {
2147 /* If all you have is a QIODevice pointer to an abstractsocket, you cannot check
2148 this, so you cannot avoid this warning. */
2149// qWarning("QAbstractSocket::waitForReadyRead() is not allowed in UnconnectedState");
2150 return false;
2151 }
2152
2153 QDeadlineTimer deadline{msecs};
2154
2155 // handle a socket in connecting state
2156 if (state() == HostLookupState || state() == ConnectingState) {
2157 if (!waitForConnected(msecs))
2158 return false;
2159 }
2160
2161 do {
2162 if (state() != ConnectedState && state() != BoundState)
2163 return false;
2164 Q_ASSERT(d->socketEngine);
2165
2166 bool readyToRead = false;
2167 bool readyToWrite = false;
2168 if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, !d->writeBuffer.isEmpty(),
2169 deadline)) {
2170#if defined (QABSTRACTSOCKET_DEBUG)
2171 qDebug("QAbstractSocket::waitForReadyRead(%i) failed (%i, %s)",
2172 msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData());
2173#endif
2174 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
2175 if (d->socketError != SocketTimeoutError)
2176 close();
2177 return false;
2178 }
2179
2180 if (readyToRead) {
2181 if (d->canReadNotification())
2182 return true;
2183 }
2184
2185 if (readyToWrite)
2186 d->canWriteNotification();
2187 } while (!deadline.hasExpired());
2188 return false;
2189}
2190
2208{
2209 Q_D(QAbstractSocket);
2210#if defined (QABSTRACTSOCKET_DEBUG)
2211 qDebug("QAbstractSocket::waitForBytesWritten(%i)", msecs);
2212#endif
2213
2214 // require calling connectToHost() before waitForBytesWritten()
2215 if (state() == UnconnectedState) {
2216 qWarning("QAbstractSocket::waitForBytesWritten() is not allowed in UnconnectedState");
2217 return false;
2218 }
2219
2220 if (d->writeBuffer.isEmpty())
2221 return false;
2222
2223 QDeadlineTimer deadline{msecs};
2224
2225 // handle a socket in connecting state
2226 if (state() == HostLookupState || state() == ConnectingState) {
2227 if (!waitForConnected(msecs))
2228 return false;
2229 }
2230
2231 for (;;) {
2232 bool readyToRead = false;
2233 bool readyToWrite = false;
2234 if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite,
2235 !d->readBufferMaxSize || d->buffer.size() < d->readBufferMaxSize,
2236 !d->writeBuffer.isEmpty(),
2237 deadline)) {
2238#if defined (QABSTRACTSOCKET_DEBUG)
2239 qDebug("QAbstractSocket::waitForBytesWritten(%i) failed (%i, %s)",
2240 msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData());
2241#endif
2242 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
2243 if (d->socketError != SocketTimeoutError)
2244 close();
2245 return false;
2246 }
2247
2248 if (readyToRead) {
2249#if defined (QABSTRACTSOCKET_DEBUG)
2250 qDebug("QAbstractSocket::waitForBytesWritten calls canReadNotification");
2251#endif
2252 d->canReadNotification();
2253 }
2254
2255
2256 if (readyToWrite) {
2257 if (d->canWriteNotification()) {
2258#if defined (QABSTRACTSOCKET_DEBUG)
2259 qDebug("QAbstractSocket::waitForBytesWritten returns true");
2260#endif
2261 return true;
2262 }
2263 }
2264
2265 if (state() != ConnectedState)
2266 return false;
2267 }
2268 return false;
2269}
2270
2292{
2293 Q_D(QAbstractSocket);
2294
2295 // require calling connectToHost() before waitForDisconnected()
2296 if (state() == UnconnectedState) {
2297 qWarning("QAbstractSocket::waitForDisconnected() is not allowed in UnconnectedState");
2298 return false;
2299 }
2300
2301 QDeadlineTimer deadline{msecs};
2302
2303 // handle a socket in connecting state
2304 if (state() == HostLookupState || state() == ConnectingState) {
2305 if (!waitForConnected(msecs))
2306 return false;
2307 if (state() == UnconnectedState)
2308 return true;
2309 }
2310
2311 for (;;) {
2312 bool readyToRead = false;
2313 bool readyToWrite = false;
2314 if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, state() == ConnectedState,
2315 !d->writeBuffer.isEmpty(),
2316 deadline)) {
2317#if defined (QABSTRACTSOCKET_DEBUG)
2318 qDebug("QAbstractSocket::waitForReadyRead(%i) failed (%i, %s)",
2319 msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData());
2320#endif
2321 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
2322 if (d->socketError != SocketTimeoutError)
2323 close();
2324 return false;
2325 }
2326
2327 if (readyToRead)
2328 d->canReadNotification();
2329 if (readyToWrite)
2330 d->canWriteNotification();
2331
2332 if (state() == UnconnectedState)
2333 return true;
2334 }
2335 return false;
2336}
2337
2346{
2347 Q_D(QAbstractSocket);
2348#if defined (QABSTRACTSOCKET_DEBUG)
2349 qDebug("QAbstractSocket::abort()");
2350#endif
2351 d->setWriteChannelCount(0);
2352 d->abortCalled = true;
2353 close();
2354}
2355
2359{
2360 return true;
2361}
2362
2378{
2379 return d_func()->flush();
2380}
2381
2385{
2386 Q_D(QAbstractSocket);
2387
2388 // if we're not connected, return -1 indicating EOF
2389 if (!d->socketEngine || !d->socketEngine->isValid() || d->state != QAbstractSocket::ConnectedState)
2390 return maxSize ? qint64(-1) : qint64(0);
2391
2392 qint64 readBytes = (maxSize && !d->isBuffered) ? d->socketEngine->read(data, maxSize)
2393 : qint64(0);
2394 if (readBytes == -2) {
2395 // -2 from the engine means no bytes available (EAGAIN) so read more later
2396 readBytes = 0;
2397 }
2398 if (readBytes < 0) {
2399 d->setError(d->socketEngine->error(), d->socketEngine->errorString());
2400 d->resetSocketLayer();
2402 } else {
2403 // Only do this when there was no error
2404 d->hasPendingData = false;
2405 d->socketEngine->setReadNotificationEnabled(true);
2406 }
2407
2408#if defined (QABSTRACTSOCKET_DEBUG)
2409 qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld [engine]", data,
2410 QtDebugUtils::toPrintable(data, readBytes, 32).constData(), maxSize, readBytes);
2411#endif
2412 return readBytes;
2413}
2414
2418{
2419 return QIODevice::readLineData(data, maxlen);
2420}
2421
2425{
2426 Q_D(QAbstractSocket);
2428 || (!d->socketEngine && d->socketType != TcpSocket && !d->isBuffered)) {
2429 d->setError(UnknownSocketError, tr("Socket is not connected"));
2430 return -1;
2431 }
2432
2433 if (!d->isBuffered && d->socketType == TcpSocket
2434 && d->socketEngine && d->writeBuffer.isEmpty()) {
2435 // This code is for the new Unbuffered QTcpSocket use case
2436 qint64 written = size ? d->socketEngine->write(data, size) : Q_INT64_C(0);
2437 if (written < 0) {
2438 d->setError(d->socketEngine->error(), d->socketEngine->errorString());
2439 } else if (written < size) {
2440 // Buffer what was not written yet
2441 d->writeBuffer.append(data + written, size - written);
2442 written = size;
2443 d->socketEngine->setWriteNotificationEnabled(true);
2444 }
2445
2446#if defined (QABSTRACTSOCKET_DEBUG)
2447 qDebug("QAbstractSocket::writeData(%p \"%s\", %lli) == %lli", data,
2448 QtDebugUtils::toPrintable(data, size, 32).constData(), size, written);
2449#endif
2450 return written; // written = actually written + what has been buffered
2451 } else if (!d->isBuffered && d->socketType != TcpSocket) {
2452 // This is for a QUdpSocket that was connect()ed
2453 qint64 written = d->socketEngine->write(data, size);
2454 if (written < 0)
2455 d->setError(d->socketEngine->error(), d->socketEngine->errorString());
2456
2457#if defined (QABSTRACTSOCKET_DEBUG)
2458 qDebug("QAbstractSocket::writeData(%p \"%s\", %lli) == %lli", data,
2459 QtDebugUtils::toPrintable(data, size, 32).constData(), size, written);
2460#endif
2461 if (written >= 0)
2462 d->emitBytesWritten(written);
2463 return written;
2464 }
2465
2466 // This is the code path for normal buffered QTcpSocket or
2467 // unbuffered QTcpSocket when there was already something in the
2468 // write buffer and therefore we could not do a direct engine write.
2469 // We just write to our write buffer and enable the write notifier
2470 // The write notifier then flush()es the buffer.
2471
2472 d->write(data, size);
2473 qint64 written = size;
2474
2475 if (d->socketEngine && !d->writeBuffer.isEmpty())
2476 d->socketEngine->setWriteNotificationEnabled(true);
2477
2478#if defined (QABSTRACTSOCKET_DEBUG)
2479 qDebug("QAbstractSocket::writeData(%p \"%s\", %lli) == %lli", data,
2480 QtDebugUtils::toPrintable(data, size, 32).constData(), size, written);
2481#endif
2482 return written;
2483}
2484
2501{
2502 Q_D(QAbstractSocket);
2503 d->localPort = port;
2504}
2505
2523{
2524 Q_D(QAbstractSocket);
2525 d->localAddress = address;
2526}
2527
2542{
2543 Q_D(QAbstractSocket);
2544 d->peerPort = port;
2545}
2546
2561{
2562 Q_D(QAbstractSocket);
2563 d->peerAddress = address;
2564}
2565
2579{
2580 Q_D(QAbstractSocket);
2581 d->peerName = name;
2582}
2583
2594{
2595 Q_D(QAbstractSocket);
2596#if defined(QABSTRACTSOCKET_DEBUG)
2597 qDebug("QAbstractSocket::close()");
2598#endif
2600 if (d->state != UnconnectedState)
2602}
2603
2613{
2614 Q_D(QAbstractSocket);
2615#if defined(QABSTRACTSOCKET_DEBUG)
2616 qDebug("QAbstractSocket::disconnectFromHost()");
2617#endif
2618
2619 if (d->state == UnconnectedState) {
2620#if defined(QABSTRACTSOCKET_DEBUG)
2621 qDebug("QAbstractSocket::disconnectFromHost() was called on an unconnected socket");
2622#endif
2623 return;
2624 }
2625
2626 if (!d->abortCalled && (d->state == ConnectingState || d->state == HostLookupState)) {
2627#if defined(QABSTRACTSOCKET_DEBUG)
2628 qDebug("QAbstractSocket::disconnectFromHost() but we're still connecting");
2629#endif
2630 d->pendingClose = true;
2631 return;
2632 }
2633
2634 // Disable and delete read notification
2635 if (d->socketEngine)
2636 d->socketEngine->setReadNotificationEnabled(false);
2637
2638 if (d->abortCalled) {
2639#if defined(QABSTRACTSOCKET_DEBUG)
2640 qDebug("QAbstractSocket::disconnectFromHost() aborting immediately");
2641#endif
2642 if (d->state == HostLookupState) {
2643 QHostInfo::abortHostLookup(d->hostLookupId);
2644 d->hostLookupId = -1;
2645 }
2646 } else {
2647 // Perhaps emit closing()
2648 if (d->state != ClosingState) {
2649 d->state = ClosingState;
2650#if defined(QABSTRACTSOCKET_DEBUG)
2651 qDebug("QAbstractSocket::disconnectFromHost() emits stateChanged()(ClosingState)");
2652#endif
2653 emit stateChanged(d->state);
2654 } else {
2655#if defined(QABSTRACTSOCKET_DEBUG)
2656 qDebug("QAbstractSocket::disconnectFromHost() return from delayed close");
2657#endif
2658 }
2659
2660 // Wait for pending data to be written.
2661 if (d->socketEngine && d->socketEngine->isValid() && (!d->allWriteBuffersEmpty()
2662 || d->socketEngine->bytesToWrite() > 0)) {
2663 d->socketEngine->setWriteNotificationEnabled(true);
2664
2665#if defined(QABSTRACTSOCKET_DEBUG)
2666 qDebug("QAbstractSocket::disconnectFromHost() delaying disconnect");
2667#endif
2668 return;
2669 } else {
2670#if defined(QABSTRACTSOCKET_DEBUG)
2671 qDebug("QAbstractSocket::disconnectFromHost() disconnecting immediately");
2672#endif
2673 }
2674 }
2675
2676 SocketState previousState = d->state;
2677 d->resetSocketLayer();
2678 d->state = UnconnectedState;
2679 emit stateChanged(d->state);
2680 emit readChannelFinished(); // we got an EOF
2681
2682 // only emit disconnected if we were connected before
2683 if (previousState == ConnectedState || previousState == ClosingState)
2685
2686 d->localPort = 0;
2687 d->peerPort = 0;
2688 d->localAddress.clear();
2689 d->peerAddress.clear();
2690 d->peerName.clear();
2691 d->setWriteChannelCount(0);
2692
2693#if defined(QABSTRACTSOCKET_DEBUG)
2694 qDebug("QAbstractSocket::disconnectFromHost() disconnected!");
2695#endif
2696
2697}
2698
2710{
2711 return d_func()->readBufferMaxSize;
2712}
2713
2737{
2738 Q_D(QAbstractSocket);
2739
2740 if (d->readBufferMaxSize == size)
2741 return;
2742 d->readBufferMaxSize = size;
2743
2744 // Do not change the notifier unless we are connected.
2745 if (d->socketEngine && d->state == QAbstractSocket::ConnectedState) {
2746 // Ensure that the read notification is enabled if we've now got
2747 // room in the read buffer.
2748 d->socketEngine->setReadNotificationEnabled(size == 0 || d->buffer.size() < size);
2749 }
2750}
2751
2758{
2759 return d_func()->state;
2760}
2761
2768{
2769 d_func()->state = state;
2770}
2771
2778{
2779 return d_func()->socketType;
2780}
2781
2788{
2789 return d_func()->socketError;
2790}
2791
2798{
2799 d_func()->socketError = socketError;
2800}
2801
2802#ifndef QT_NO_NETWORKPROXY
2823{
2824 Q_D(QAbstractSocket);
2825 d->proxy = networkProxy;
2826}
2827
2838{
2839 Q_D(const QAbstractSocket);
2840 return d->proxy;
2841}
2842
2855{
2856 Q_D(const QAbstractSocket);
2857 return d->protocolTag;
2858}
2859
2869{
2870 Q_D(QAbstractSocket);
2871 d->protocolTag = tag;
2872}
2873
2874#endif // QT_NO_NETWORKPROXY
2875
2876#ifndef QT_NO_DEBUG_STREAM
2878{
2879 QDebugStateSaver saver(debug);
2880 debug.resetFormat().nospace();
2881 switch (error) {
2883 debug << "QAbstractSocket::ConnectionRefusedError";
2884 break;
2886 debug << "QAbstractSocket::RemoteHostClosedError";
2887 break;
2889 debug << "QAbstractSocket::HostNotFoundError";
2890 break;
2892 debug << "QAbstractSocket::SocketAccessError";
2893 break;
2895 debug << "QAbstractSocket::SocketResourceError";
2896 break;
2898 debug << "QAbstractSocket::SocketTimeoutError";
2899 break;
2901 debug << "QAbstractSocket::DatagramTooLargeError";
2902 break;
2904 debug << "QAbstractSocket::NetworkError";
2905 break;
2907 debug << "QAbstractSocket::AddressInUseError";
2908 break;
2910 debug << "QAbstractSocket::SocketAddressNotAvailableError";
2911 break;
2913 debug << "QAbstractSocket::UnsupportedSocketOperationError";
2914 break;
2916 debug << "QAbstractSocket::UnfinishedSocketOperationError";
2917 break;
2919 debug << "QAbstractSocket::ProxyAuthenticationRequiredError";
2920 break;
2922 debug << "QAbstractSocket::UnknownSocketError";
2923 break;
2925 debug << "QAbstractSocket::ProxyConnectionRefusedError";
2926 break;
2928 debug << "QAbstractSocket::ProxyConnectionClosedError";
2929 break;
2931 debug << "QAbstractSocket::ProxyConnectionTimeoutError";
2932 break;
2934 debug << "QAbstractSocket::ProxyNotFoundError";
2935 break;
2937 debug << "QAbstractSocket::ProxyProtocolError";
2938 break;
2939 default:
2940 debug << "QAbstractSocket::SocketError(" << int(error) << ')';
2941 break;
2942 }
2943 return debug;
2944}
2945
2947{
2948 QDebugStateSaver saver(debug);
2949 debug.resetFormat().nospace();
2950 switch (state) {
2952 debug << "QAbstractSocket::UnconnectedState";
2953 break;
2955 debug << "QAbstractSocket::HostLookupState";
2956 break;
2958 debug << "QAbstractSocket::ConnectingState";
2959 break;
2961 debug << "QAbstractSocket::ConnectedState";
2962 break;
2964 debug << "QAbstractSocket::BoundState";
2965 break;
2967 debug << "QAbstractSocket::ListeningState";
2968 break;
2970 debug << "QAbstractSocket::ClosingState";
2971 break;
2972 default:
2973 debug << "QAbstractSocket::SocketState(" << int(state) << ')';
2974 break;
2975 }
2976 return debug;
2977}
2978#endif
2979
2981
2982#include "moc_qabstractsocket.cpp"
IOBluetoothL2CAPChannel * channel
QAbstractSocket::SocketError error() const
virtual void setWriteNotificationEnabled(bool enable)=0
virtual bool bind(const QHostAddress &address, quint16 port)=0
virtual bool isValid() const =0
virtual bool isReadNotificationEnabled() const =0
void setReceiver(QAbstractSocketEngineReceiver *receiver)
virtual bool hasPendingDatagrams() const =0
virtual bool connectToHost(const QHostAddress &address, quint16 port)=0
virtual bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol=QAbstractSocket::IPv4Protocol)=0
QAbstractSocket::SocketType socketType() const
virtual qint64 read(char *data, qint64 maxlen)=0
virtual void setReadNotificationEnabled(bool enable)=0
static QAbstractSocketEngine * createSocketEngine(QAbstractSocket::SocketType socketType, const QNetworkProxy &, QObject *parent)
virtual bool setOption(SocketOption option, int value)=0
virtual qint64 write(const char *data, qint64 len)=0
QAbstractSocket::SocketState state() const
virtual qintptr socketDescriptor() const =0
virtual bool connectToHostByName(const QString &name, quint16 port)=0
virtual qint64 bytesAvailable() const =0
virtual qint64 bytesToWrite() const =0
virtual void setExceptionNotificationEnabled(bool enable)=0
virtual bool isWriteNotificationEnabled() const =0
QHostAddress peerAddress() const
virtual void close()=0
virtual bool isExceptionNotificationEnabled() const =0
QHostAddress localAddress() const
QList< QHostAddress > addresses
void setError(QAbstractSocket::SocketError errorCode, const QString &errorString)
void emitBytesWritten(qint64 bytes, int channel=0)
QAbstractSocket::NetworkLayerProtocol preferredNetworkLayerProtocol
void emitReadyRead(int channel=0)
QAbstractSocket::SocketError socketError
QAbstractSocket::SocketType socketType
static QAbstractSocketEngine * getSocketEngine(QAbstractSocket *)
void _q_startConnecting(const QHostInfo &hostInfo)
QAbstractSocketEngine * socketEngine
void startConnectingByName(const QString &host)
virtual bool canReadNotification()
void resolveProxy(const QString &hostName, quint16 port)
virtual void configureCreatedSocket()
bool initSocketLayer(QAbstractSocket::NetworkLayerProtocol protocol)
static void pauseSocketNotifiers(QAbstractSocket *)
virtual bool bind(const QHostAddress &address, quint16 port, QAbstractSocket::BindMode mode)
QAbstractSocket::SocketState state
static void resumeSocketNotifiers(QAbstractSocket *)
void connectionNotification() override
void setErrorAndEmit(QAbstractSocket::SocketError errorCode, const QString &errorString)
The QAbstractSocket class provides the base functionality common to all socket types.
SocketState
This enum describes the different states in which a socket can be.
bool flush()
This function writes as much as possible from the internal write buffer to the underlying network soc...
bool isSequential() const override
\reimp
QAbstractSocket(SocketType socketType, QObject *parent)
Creates a new abstract socket of type socketType.
void stateChanged(QAbstractSocket::SocketState)
This signal is emitted whenever QAbstractSocket's state changes.
virtual void setReadBufferSize(qint64 size)
Sets the size of QAbstractSocket's internal read buffer to be size bytes.
quint16 peerPort() const
Returns the port of the connected peer if the socket is in ConnectedState; otherwise returns 0.
static constexpr auto IPv4Protocol
void abort()
Aborts the current connection and resets the socket.
virtual void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
virtual QVariant socketOption(QAbstractSocket::SocketOption option)
void setPauseMode(PauseModes pauseMode)
bool waitForReadyRead(int msecs=30000) override
This function blocks until new data is available for reading and the \l{QIODevice::}{readyRead()} sig...
qint64 bytesToWrite() const override
Returns the number of bytes that are waiting to be written.
qint64 readLineData(char *data, qint64 maxlen) override
\reimp
bool waitForBytesWritten(int msecs=30000) override
\reimp
virtual qintptr socketDescriptor() const
Returns the native socket descriptor of the QAbstractSocket object if this is available; otherwise re...
virtual bool waitForDisconnected(int msecs=30000)
Waits until the socket has disconnected, up to msecs milliseconds.
QString protocolTag() const
void setSocketError(SocketError socketError)
Sets the type of error that last occurred to socketError.
void setPeerPort(quint16 port)
virtual ~QAbstractSocket()
Destroys the socket.
qint64 bytesAvailable() const override
Returns the number of incoming bytes that are waiting to be read.
QHostAddress localAddress() const
Returns the host address of the local socket if available; otherwise returns QHostAddress::Null.
QString peerName() const
Returns the name of the peer as specified by connectToHost(), or an empty QString if connectToHost() ...
qint64 skipData(qint64 maxSize) override
\reimp
QNetworkProxy proxy() const
virtual bool bind(const QHostAddress &address, quint16 port=0, BindMode mode=DefaultForPlatform)
virtual bool waitForConnected(int msecs=30000)
Waits until the socket is connected, up to msecs milliseconds.
PauseModes pauseMode() const
virtual void disconnectFromHost()
Attempts to close the socket.
void setPeerAddress(const QHostAddress &address)
static constexpr auto UnknownNetworkLayerProtocol
void setProxy(const QNetworkProxy &networkProxy)
static constexpr auto AnyIPProtocol
qint64 writeData(const char *data, qint64 len) override
\reimp
qint64 readBufferSize() const
Returns the size of the internal read buffer.
void setLocalPort(quint16 port)
void setProtocolTag(const QString &tag)
SocketType socketType() const
Returns the socket type (TCP, UDP, or other).
bool isValid() const
Returns true if the socket is valid and ready for use; otherwise returns false.
void close() override
Closes the I/O device for the socket and calls disconnectFromHost() to close the socket's connection.
void setLocalAddress(const QHostAddress &address)
SocketState state() const
Returns the state of the socket.
SocketError
This enum describes the socket errors that can occur.
void setSocketState(SocketState state)
Sets the state of the socket to state.
static constexpr auto IPv6Protocol
SocketType
This enum describes the transport layer protocol.
virtual void connectToHost(const QString &hostName, quint16 port, OpenMode mode=ReadWrite, NetworkLayerProtocol protocol=AnyIPProtocol)
Attempts to make a connection to hostName on the given port.
quint16 localPort() const
Returns the host port number (in native byte order) of the local socket if available; otherwise retur...
void setPeerName(const QString &name)
virtual void resume()
void disconnected()
This signal is emitted when the socket has been disconnected.
SocketError error() const
Returns the type of error that last occurred.
QHostAddress peerAddress() const
Returns the address of the connected peer if the socket is in ConnectedState; otherwise returns QHost...
virtual bool setSocketDescriptor(qintptr socketDescriptor, SocketState state=ConnectedState, OpenMode openMode=ReadWrite)
Initializes QAbstractSocket with the native socket descriptor socketDescriptor.
qint64 readData(char *data, qint64 maxlen) override
\reimp
Type loadRelaxed() const noexcept
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
\inmodule QtCore
bool hasExpired() const noexcept
Returns true if this QDeadlineTimer object has expired, false if there remains time left.
constexpr bool isForever() const noexcept
Returns true if this QDeadlineTimer object never expires, false otherwise.
std::chrono::nanoseconds remainingTimeAsDuration() const noexcept
Returns the time remaining before the deadline.
\inmodule QtCore
\inmodule QtCore
The QHostAddress class provides an IP address.
void setAddress(quint32 ip4Addr)
Set the IPv4 address specified by ip4Addr.
QString toString() const
Returns the address as a string.
NetworkLayerProtocol protocol() const
Returns the network layer protocol of the host address.
The QHostInfo class provides static functions for host name lookups.
Definition qhostinfo.h:19
static void abortHostLookup(int lookupId)
Aborts the host lookup with the ID id, as returned by lookupHost().
void setAddresses(const QList< QHostAddress > &addresses)
Sets the list of addresses in this QHostInfo to addresses.
static QHostInfo fromName(const QString &name)
Looks up the IP address(es) for the given host name.
void write(const char *data, qint64 size)
bool allWriteBuffersEmpty() const
void setReadChannelCount(int count)
qint64 read(char *data, qint64 maxSize, bool peeking=false)
void setWriteChannelCount(int count)
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual bool open(QIODeviceBase::OpenMode mode)
Opens the device and sets its OpenMode to mode.
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
bool isOpen() const
Returns true if the device is open; otherwise returns false.
bool isReadable() const
Returns true if data can be read from the device; otherwise returns false.
QIODeviceBase::OpenMode openMode() const
Returns the mode in which the device has been opened; i.e.
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
virtual qint64 skipData(qint64 maxSize)
bool isWritable() const
Returns true if data can be written to the device; otherwise returns false.
virtual qint64 readLineData(char *data, qint64 maxlen)
Reads up to maxSize characters into data and returns the number of characters read.
virtual qint64 bytesToWrite() const
For buffered devices, this function returns the number of bytes waiting to be written.
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
void readChannelFinished()
bool isEmpty() const noexcept
Definition qlist.h:401
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
value_type takeFirst()
Definition qlist.h:566
qsizetype count() const noexcept
Definition qlist.h:398
void clear()
Definition qlist.h:434
static QList< QNetworkProxy > proxyForQuery(const QNetworkProxyQuery &query)
This function takes the query request, query, examines the details of the type of socket or request a...
The QNetworkProxyQuery class is used to query the proxy settings for a socket.
The QNetworkProxy class provides a network layer proxy.
QNetworkProxy::ProxyType type() const
Returns the proxy type for this instance.
QAtomicPointer< QThreadData > threadData
Definition qobject_p.h:203
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QByteArray toLatin1() const &
Definition qstring.h:630
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
\inmodule QtCore
Definition qtimer.h:20
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
Definition qtimer.cpp:241
int remainingTime
the remaining time in milliseconds
Definition qtimer.h:24
void stop()
Stops the timer.
Definition qtimer.cpp:267
\inmodule QtCore
Definition qvariant.h:65
else opt state
[0]
Combined button and popup list for selecting options.
Q_CORE_EXPORT QByteArray toPrintable(const char *data, qint64 len, qsizetype maxSize)
Definition qdebug.cpp:24
@ QueuedConnection
@ DirectConnection
static constexpr auto DefaultConnectTimeout
static bool isProxyError(QAbstractSocket::SocketError error)
Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, QAbstractSocket::SocketError error)
#define QABSTRACTSOCKET_BUFFERSIZE
AudioChannelLayoutTag tag
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
EGLOutputPortEXT port
static QT_BEGIN_NAMESPACE const char * socketType(QSocketNotifier::Type type)
QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id)
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
return ret
static ControlElement< T > * ptr(QWidget *widget)
static const QMetaObjectPrivate * priv(const uint *data)
#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
Definition qmetatype.h:1384
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLenum mode
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLbitfield GLuint64 timeout
[4]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint buffer
GLuint name
GLdouble s
[6]
Definition qopenglext.h:235
GLenum query
GLuint writeBuffer
GLuint GLuint64EXT address
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLuint GLenum option
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static QLatin1StringView typeStr(QShaderDescription::VariableType t)
#define qPrintable(string)
Definition qstring.h:1531
#define QT_CONFIG(feature)
#define tr(X)
#define emit
unsigned short quint16
Definition qtypes.h:48
long long qint64
Definition qtypes.h:60
#define Q_INT64_C(c)
Definition qtypes.h:57
ptrdiff_t qintptr
Definition qtypes.h:166
QDeadlineTimer deadline(30s)
QTcpSocket * socket
[1]
QTimer * timer
[3]
QHostInfo info
[0]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...