Qt 6.x
The Qt SDK
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
429#include <QtNetwork/private/qtnetworkglobal_p.h>
430
431#include "qabstractsocket.h"
432#include "qabstractsocket_p.h"
433
434#include "private/qhostinfo_p.h"
435
437#include <qhostaddress.h>
438#include <qhostinfo.h>
439#include <qmetaobject.h>
440#include <qpointer.h>
441#include <qtimer.h>
442#include <qelapsedtimer.h>
443#include <qscopedvaluerollback.h>
444#include <qvarlengtharray.h>
445
446#include <private/qthread_p.h>
447
448#ifdef QABSTRACTSOCKET_DEBUG
449#include <qdebug.h>
450#include <private/qdebug_p.h>
451#endif
452
453#include <time.h>
454
455#define Q_CHECK_SOCKETENGINE(returnValue) do { \
456 if (!d->socketEngine) { \
457 return returnValue; \
458 } } while (0)
459
460#ifndef QABSTRACTSOCKET_BUFFERSIZE
461#define QABSTRACTSOCKET_BUFFERSIZE 32768
462#endif
463#define QT_TRANSFER_TIMEOUT 120000
464
466
467using namespace Qt::StringLiterals;
468
471
472static const int DefaultConnectTimeout = 30000;
473
474static bool isProxyError(QAbstractSocket::SocketError error)
475{
476 switch (error) {
483 return true;
484 default:
485 return false;
486 }
487}
488
494{
496}
497
504{
505}
506
512{
513#if defined (QABSTRACTSOCKET_DEBUG)
514 qDebug("QAbstractSocketPrivate::resetSocketLayer()");
515#endif
516
517 hasPendingData = false;
518 if (socketEngine) {
521 delete socketEngine;
522 socketEngine = nullptr;
524 }
525 if (connectTimer)
527}
528
536{
537#ifdef QT_NO_NETWORKPROXY
538 // this is here to avoid a duplication of the call to createSocketEngine below
539 static const QNetworkProxy &proxyInUse = *(QNetworkProxy *)0;
540#endif
541
542 Q_Q(QAbstractSocket);
543#if defined (QABSTRACTSOCKET_DEBUG)
545 if (q->socketType() == QAbstractSocket::TcpSocket) typeStr = "TcpSocket"_L1;
546 else if (q->socketType() == QAbstractSocket::UdpSocket) typeStr = "UdpSocket"_L1;
547 else if (q->socketType() == QAbstractSocket::SctpSocket) typeStr = "SctpSocket"_L1;
548 else typeStr = "UnknownSocketType"_L1;
549 QString protocolStr;
550 if (protocol == QAbstractSocket::IPv4Protocol) protocolStr = "IPv4Protocol"_L1;
551 else if (protocol == QAbstractSocket::IPv6Protocol) protocolStr = "IPv6Protocol"_L1;
552 else protocolStr = "UnknownNetworkLayerProtocol"_L1;
553#endif
554
557 if (!socketEngine) {
559 QAbstractSocket::tr("Operation on socket is not supported"));
560 return false;
561 }
562 if (!socketEngine->initialize(q->socketType(), protocol)) {
563#if defined (QABSTRACTSOCKET_DEBUG)
564 qDebug("QAbstractSocketPrivate::initSocketLayer(%s, %s) failed (%s)",
565 typeStr.toLatin1().constData(), protocolStr.toLatin1().constData(),
567#endif
569 return false;
570 }
571
573
574 if (threadData.loadRelaxed()->hasEventDispatcher())
576
577#if defined (QABSTRACTSOCKET_DEBUG)
578 qDebug("QAbstractSocketPrivate::initSocketLayer(%s, %s) success",
579 typeStr.toLatin1().constData(), protocolStr.toLatin1().constData());
580#endif
581 return true;
582}
583
587{
588#ifndef QT_NO_SCTP
589 Q_Q(QAbstractSocket);
590 // Set single stream mode for unbuffered SCTP socket
593#endif
594}
595
603{
604 Q_Q(QAbstractSocket);
605#if defined (QABSTRACTSOCKET_DEBUG)
606 qDebug("QAbstractSocketPrivate::canReadNotification()");
607#endif
608
609 // If buffered, read data from the socket into the read buffer
610 if (isBuffered) {
611 const qint64 oldBufferSize = buffer.size();
612
613 // Return if there is no space in the buffer
614 if (readBufferMaxSize && oldBufferSize >= readBufferMaxSize) {
616#if defined (QABSTRACTSOCKET_DEBUG)
617 qDebug("QAbstractSocketPrivate::canReadNotification() buffer is full");
618#endif
619 return false;
620 }
621
622 // If reading from the socket fails after getting a read
623 // notification, close the socket.
624 if (!readFromSocket()) {
625#if defined (QABSTRACTSOCKET_DEBUG)
626 qDebug("QAbstractSocketPrivate::canReadNotification() disconnecting socket");
627#endif
628 q->disconnectFromHost();
629 return false;
630 }
631
632 // Return if there is no new data available.
633 if (buffer.size() == oldBufferSize) {
634 // If the socket is opened only for writing, return true
635 // to indicate that the data was discarded.
636 return !q->isReadable();
637 }
638 } else {
639 if (hasPendingData) {
641 return true;
642 }
643 hasPendingData = true;
644 }
645
647
648#if defined (QABSTRACTSOCKET_DEBUG)
649 // If we were closed as a result of the readyRead() signal.
651 qDebug("QAbstractSocketPrivate::canReadNotification() socket is closing - returning");
652#endif
653
654 return true;
655}
656
663{
664 Q_Q(QAbstractSocket);
665 // Note that this method is only called on Windows. Other platforms close in the canReadNotification()
666
667#if defined (QABSTRACTSOCKET_DEBUG)
668 qDebug("QAbstractSocketPrivate::canCloseNotification()");
669#endif
670
671 qint64 newBytes = 0;
672 if (isBuffered) {
673 // Try to read to the buffer, if the read fail we can close the socket.
674 newBytes = buffer.size();
675 qint64 oldReadBufferMaxSize = readBufferMaxSize;
676 readBufferMaxSize = 0; // temporarily disable max read buffer, we want to empty the OS buffer
677 bool hadReadFromSocket = readFromSocket();
678 readBufferMaxSize = oldReadBufferMaxSize;
679 if (!hadReadFromSocket) {
680 q->disconnectFromHost();
681 return;
682 }
683 newBytes = buffer.size() - newBytes;
684 if (newBytes) {
685 // If there was still some data to be read from the socket
686 // then we could get another FD_READ. The disconnect will
687 // then occur when we read from the socket again and fail
688 // in canReadNotification or by the manually created
689 // closeNotification below.
691
693 }
694 } else if ((socketType == QAbstractSocket::TcpSocket ||
697 }
698}
699
700
707{
708#if defined (QABSTRACTSOCKET_DEBUG)
709 qDebug("QAbstractSocketPrivate::canWriteNotification() flushing");
710#endif
711
712 return writeToSocket();
713}
714
721{
722 // If in connecting state, check if the connection has been
723 // established, otherwise flush pending data.
725#if defined (QABSTRACTSOCKET_DEBUG)
726 qDebug("QAbstractSocketPrivate::connectionNotification() testing connection");
727#endif
729 }
730}
731
742{
743 Q_Q(QAbstractSocket);
744 if (!socketEngine || !socketEngine->isValid() || (writeBuffer.isEmpty()
745 && socketEngine->bytesToWrite() == 0)) {
746#if defined (QABSTRACTSOCKET_DEBUG)
747 qDebug("QAbstractSocketPrivate::writeToSocket() nothing to do: valid ? %s, writeBuffer.isEmpty() ? %s",
748 (socketEngine && socketEngine->isValid()) ? "yes" : "no", writeBuffer.isEmpty() ? "yes" : "no");
749#endif
750
751 // this covers the case when the buffer was empty, but we had to wait for the socket engine to finish
753 q->disconnectFromHost();
754 } else {
755 if (socketEngine)
757 }
758
759 return false;
760 }
761
762 qint64 nextSize = writeBuffer.nextDataBlockSize();
763 const char *ptr = writeBuffer.readPointer();
764
765 // Attempt to write it all in one chunk.
766 qint64 written = nextSize ? socketEngine->write(ptr, nextSize) : Q_INT64_C(0);
767 if (written < 0) {
768#if defined (QABSTRACTSOCKET_DEBUG)
769 qDebug() << "QAbstractSocketPrivate::writeToSocket() write error, aborting."
771#endif
773 // an unexpected error so close the socket.
774 q->abort();
775 return false;
776 }
777
778#if defined (QABSTRACTSOCKET_DEBUG)
779 qDebug("QAbstractSocketPrivate::writeToSocket() %lld bytes written to the network",
780 written);
781#endif
782
783 if (written > 0) {
784 // Remove what we wrote so far.
785 writeBuffer.free(written);
786
787 // Emit notifications.
788 emitBytesWritten(written);
789 }
790
791 if (writeBuffer.isEmpty() && socketEngine && !socketEngine->bytesToWrite())
794 q->disconnectFromHost();
795
796 return written > 0;
797}
798
806{
807 bool dataWasWritten = false;
808
809 while (!allWriteBuffersEmpty() && writeToSocket())
810 dataWasWritten = true;
811
812 return dataWasWritten;
813}
814
815#ifndef QT_NO_NETWORKPROXY
821{
822 QList<QNetworkProxy> proxies;
823
825 // a non-default proxy was set with setProxy
826 proxies << proxy;
827 } else {
828 // try the application settings instead
836 }
837
838 // return the first that we can use
839 for (const QNetworkProxy &p : std::as_const(proxies)) {
841 (p.capabilities() & QNetworkProxy::UdpTunnelingCapability) == 0)
842 continue;
843
845 (p.capabilities() & QNetworkProxy::TunnelingCapability) == 0)
846 continue;
847
849 (p.capabilities() & QNetworkProxy::SctpTunnelingCapability) == 0)
850 continue;
851
852 proxyInUse = p;
853 return;
854 }
855
856 // no proxy found
857 // DefaultProxy here will raise an error
859}
860#endif // !QT_NO_NETWORKPROXY
861
862#if !defined(QT_NO_NETWORKPROXY)
870{
871 Q_Q(QAbstractSocket);
873 return;
874
875#if defined(QABSTRACTSOCKET_DEBUG)
876 qDebug("QAbstractSocketPrivate::startConnectingByName(host == %s)", qPrintable(host));
877#endif
878
879 // ### Let the socket engine drive this?
881 emit q->stateChanged(state);
882
884 // Try to connect to the host. If it succeeds immediately
885 // (e.g. QSocks5SocketEngine in UDPASSOCIATE mode), emit
886 // connected() and return.
889 return;
890 }
891
893 return;
894
895 // failed to connect
897 }
898
900 emit q->errorOccurred(socketError);
901 emit q->stateChanged(state);
902}
903
904#endif // !QT_NO_NETWORKPROXY
905
914{
915 Q_Q(QAbstractSocket);
918 return;
919
920 if (hostLookupId != -1 && hostLookupId != hostInfo.lookupId()) {
921 qWarning("QAbstractSocketPrivate::_q_startConnecting() received hostInfo for wrong lookup ID %d expected %d", hostInfo.lookupId(), hostLookupId);
922 }
923
924 // Only add the addresses for the preferred network layer.
925 // Or all if preferred network layer is not set.
927 addresses = hostInfo.addresses();
928 } else {
929 const auto candidates = hostInfo.addresses();
930 for (const QHostAddress &address : candidates) {
931 if (address.protocol() == preferredNetworkLayerProtocol)
933 }
934 }
935
936
937#if defined(QABSTRACTSOCKET_DEBUG)
938 QString s = "{"_L1;
939 for (int i = 0; i < addresses.count(); ++i) {
940 if (i != 0) s += ", "_L1;
941 s += addresses.at(i).toString();
942 }
943 s += u'}';
944 qDebug("QAbstractSocketPrivate::_q_startConnecting(hostInfo == %s)", s.toLatin1().constData());
945#endif
946
947 // Try all addresses twice.
949
950 // If there are no addresses in the host list, report this to the
951 // user.
952 if (addresses.isEmpty()) {
953#if defined(QABSTRACTSOCKET_DEBUG)
954 qDebug("QAbstractSocketPrivate::_q_startConnecting(), host not found");
955#endif
957 setError(QAbstractSocket::HostNotFoundError, QAbstractSocket::tr("Host not found"));
958 emit q->stateChanged(state);
960 return;
961 }
962
963 // Enter Connecting state (see also sn_write, which is called by
964 // the write socket notifier after connect())
966 emit q->stateChanged(state);
967
968 // Report the successful host lookup
969 emit q->hostFound();
970
971 // The addresses returned by the lookup will be tested one after
972 // another by _q_connectToNextAddress().
974}
975
986{
987 Q_Q(QAbstractSocket);
988 do {
989 // Check for more pending addresses
990 if (addresses.isEmpty()) {
991#if defined(QABSTRACTSOCKET_DEBUG)
992 qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), all addresses failed.");
993#endif
995 if (socketEngine) {
997#ifdef Q_OS_AIX
998 // On AIX, the second connect call will result in EINVAL and not
999 // ECONNECTIONREFUSED; although the meaning is the same.
1001#endif
1004 QAbstractSocket::tr("Connection refused"));
1005 } else {
1007 }
1008 } else {
1009// socketError = QAbstractSocket::ConnectionRefusedError;
1010// q->setErrorString(QAbstractSocket::tr("Connection refused"));
1011 }
1012 emit q->stateChanged(state);
1013 emit q->errorOccurred(socketError);
1014 return;
1015 }
1016
1017 // Pick the first host address candidate
1019#if defined(QABSTRACTSOCKET_DEBUG)
1020 qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), connecting to %s:%i, %d left to try",
1022#endif
1023
1025 // hope that the next address is better
1026#if defined(QABSTRACTSOCKET_DEBUG)
1027 qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), failed to initialize sock layer");
1028#endif
1029 continue;
1030 }
1031
1032 // Tries to connect to the address. If it succeeds immediately
1033 // (localhost address on BSD or any UDP connect), emit
1034 // connected() and return.
1035 if (
1037 //_q_testConnection();
1039 return;
1040 }
1041
1042 // Check that we're in delayed connection state. If not, try
1043 // the next address
1045#if defined(QABSTRACTSOCKET_DEBUG)
1046 qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), connection failed (%s)",
1048#endif
1049 continue;
1050 }
1051
1052 // Start the connect timer.
1053 if (threadData.loadRelaxed()->hasEventDispatcher()) {
1054 if (!connectTimer) {
1055 connectTimer = new QTimer(q);
1059 }
1060 int connectTimeout = DefaultConnectTimeout;
1061 connectTimer->start(connectTimeout);
1062 }
1063
1064 // Wait for a write notification that will eventually call
1065 // _q_testConnection().
1067 break;
1069}
1070
1077{
1078 if (connectTimer)
1079 connectTimer->stop();
1080
1081 if (socketEngine) {
1083 // Fetch the parameters if our connection is completed;
1084 // otherwise, fall out and try the next address.
1086 if (pendingClose) {
1087 q_func()->disconnectFromHost();
1088 pendingClose = false;
1089 }
1090 return;
1091 }
1092
1093 // don't retry the other addresses if we had a proxy error
1095 addresses.clear();
1096 }
1097
1098#if defined(QABSTRACTSOCKET_DEBUG)
1099 qDebug("QAbstractSocketPrivate::_q_testConnection() connection failed,"
1100 " checking for alternative addresses");
1101#endif
1103}
1104
1113{
1114 Q_Q(QAbstractSocket);
1115#if defined(QABSTRACTSOCKET_DEBUG)
1116 qDebug("QAbstractSocketPrivate::_q_abortConnectionAttempt() (timed out)");
1117#endif
1118 if (socketEngine)
1120
1121 connectTimer->stop();
1122
1123 if (addresses.isEmpty()) {
1126 QAbstractSocket::tr("Connection timed out"));
1127 emit q->stateChanged(state);
1128 emit q->errorOccurred(socketError);
1129 } else {
1131 }
1132}
1133
1140{
1141 Q_Q(QAbstractSocket);
1142 // Find how many bytes we can read from the socket layer.
1143 qint64 bytesToRead = socketEngine->bytesAvailable();
1144 if (bytesToRead == 0) {
1145 // Under heavy load, certain conditions can trigger read notifications
1146 // for socket notifiers on which there is no activity. If we continue
1147 // to read 0 bytes from the socket, we will trigger behavior similar
1148 // to that which signals a remote close. When we hit this condition,
1149 // we try to read 4k of data from the socket, which will give us either
1150 // an EAGAIN/EWOULDBLOCK if the connection is alive (i.e., the remote
1151 // host has _not_ disappeared).
1152 bytesToRead = 4096;
1153 }
1154
1155 if (q->isReadable()) {
1156 if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - buffer.size()))
1157 bytesToRead = readBufferMaxSize - buffer.size();
1158
1159#if defined(QABSTRACTSOCKET_DEBUG)
1160 qDebug("QAbstractSocketPrivate::readFromSocket() about to read %lld bytes",
1161 bytesToRead);
1162#endif
1163
1164 // Read from the socket, store data in the read buffer.
1165 char *ptr = buffer.reserve(bytesToRead);
1166 qint64 readBytes = socketEngine->read(ptr, bytesToRead);
1167 if (readBytes == -2) {
1168 // No bytes currently available for reading.
1169 buffer.chop(bytesToRead);
1170 return true;
1171 }
1172 buffer.chop(bytesToRead - (readBytes < 0 ? qint64(0) : readBytes));
1173#if defined(QABSTRACTSOCKET_DEBUG)
1174 qDebug("QAbstractSocketPrivate::readFromSocket() got %lld bytes, buffer size = %lld",
1175 readBytes, buffer.size());
1176#endif
1177 } else {
1178 // Discard unwanted data if opened in WriteOnly mode
1179 QVarLengthArray<char, 4096> discardBuffer(bytesToRead);
1180
1181#if defined(QABSTRACTSOCKET_DEBUG)
1182 qDebug("QAbstractSocketPrivate::readFromSocket() about to discard %lld bytes",
1183 bytesToRead);
1184#endif
1185 socketEngine->read(discardBuffer.data(), bytesToRead);
1186 }
1187
1188 if (!socketEngine->isValid()) {
1189#if defined(QABSTRACTSOCKET_DEBUG)
1190 qDebug("QAbstractSocketPrivate::readFromSocket() read failed: %s",
1192#endif
1195 return false;
1196 }
1197
1198 return true;
1199}
1200
1206{
1207 Q_Q(QAbstractSocket);
1208 // Only emit readyRead() when not recursing.
1211 emittedReadyRead = true;
1212 emit q->readyRead();
1213 }
1214 // channelReadyRead() can be emitted recursively - even for the same channel.
1215 emit q->channelReadyRead(channel);
1216}
1217
1223{
1224 Q_Q(QAbstractSocket);
1225 // Only emit bytesWritten() when not recursing.
1228 emittedBytesWritten = true;
1229 emit q->bytesWritten(bytes);
1230 }
1231 // channelBytesWritten() can be emitted recursively - even for the same channel.
1232 emit q->channelBytesWritten(channel, bytes);
1233}
1234
1240{
1241 Q_Q(QAbstractSocket);
1242
1244 if (socketEngine) {
1245 if (q->isReadable()) {
1246 const int inboundStreamCount = socketEngine->inboundStreamCount();
1247 setReadChannelCount(qMax(1, inboundStreamCount));
1248 if (inboundStreamCount == 0)
1249 readChannelCount = 0;
1250 }
1251 if (q->isWritable()) {
1252 const int outboundStreamCount = socketEngine->outboundStreamCount();
1253 setWriteChannelCount(qMax(1, outboundStreamCount));
1254 if (outboundStreamCount == 0)
1256 }
1264 }
1265
1267#if defined(QABSTRACTSOCKET_DEBUG)
1268 qDebug("QAbstractSocketPrivate::fetchConnectionParameters() connection to %s:%i established",
1270#endif
1271 emit q->stateChanged(state);
1272 emit q->connected();
1273}
1274
1278{
1279 Q_D(const QAbstractSocket);
1280
1281 // if we're not connected, return -1 indicating EOF
1282 if (!d->socketEngine || !d->socketEngine->isValid()
1284 return -1;
1285
1286 // Caller, QIODevice::skip(), has ensured buffer is empty. So, wait
1287 // for more data in buffered mode.
1288 if (d->isBuffered)
1289 return 0;
1290
1291 return QIODevice::skipData(maxSize);
1292}
1293
1295{
1296 QAbstractSocketEngine *socketEngine = socket->d_func()->socketEngine;
1297 if (!socketEngine)
1298 return;
1302
1303#ifdef QABSTRACTSOCKET_DEBUG
1305 << "pause notifiers, storing 'true' states, currently read:" << read
1306 << "write:" << write << "except:" << except;
1307#endif
1308 // We do this if-check to avoid accidentally overwriting any previously stored state
1309 // It will reset to false once the socket is re-enabled.
1310 if (read) {
1311 socket->d_func()->prePauseReadSocketNotifierState = true;
1313 }
1314 if (write) {
1315 socket->d_func()->prePauseWriteSocketNotifierState = true;
1317 }
1318 if (except) {
1319 socket->d_func()->prePauseExceptionSocketNotifierState = true;
1321 }
1322}
1323
1325{
1326 QAbstractSocketEngine *socketEngine = socket->d_func()->socketEngine;
1327 if (!socketEngine)
1328 return;
1329 QAbstractSocketPrivate *priv = socket->d_func();
1330#ifdef QABSTRACTSOCKET_DEBUG
1332 << "Maybe resume notifiers, read:" << priv->prePauseReadSocketNotifierState
1333 << "write:" << priv->prePauseWriteSocketNotifierState
1334 << "exception:" << priv->prePauseExceptionSocketNotifierState;
1335#endif
1336 if (std::exchange(priv->prePauseReadSocketNotifierState, false))
1338 if (std::exchange(priv->prePauseWriteSocketNotifierState, false))
1340 if (std::exchange(priv->prePauseExceptionSocketNotifierState, false))
1342}
1343
1345{
1346 return socket->d_func()->socketEngine;
1347}
1348
1355 const QString &errStr)
1356{
1357 socketError = errorCode;
1358 errorString = errStr;
1359}
1360
1368 const QString &errorString)
1369{
1370 Q_Q(QAbstractSocket);
1371 setError(errorCode, errorString);
1372 emit q->errorOccurred(errorCode);
1373}
1374
1382 : QIODevice(dd, parent)
1383{
1384 Q_D(QAbstractSocket);
1385#if defined(QABSTRACTSOCKET_DEBUG)
1386 qDebug("QAbstractSocket::QAbstractSocket(%sSocket, QAbstractSocketPrivate == %p, parent == %p)",
1387 socketType == TcpSocket ? "Tcp" : socketType == UdpSocket ? "Udp"
1388 : socketType == SctpSocket ? "Sctp" : "Unknown", &dd, parent);
1389#endif
1390 d->socketType = socketType;
1391}
1392
1401{
1402}
1403
1408{
1409 Q_D(QAbstractSocket);
1410#if defined(QABSTRACTSOCKET_DEBUG)
1411 qDebug("QAbstractSocket::~QAbstractSocket()");
1412#endif
1413 if (d->state != UnconnectedState)
1414 abort();
1415}
1416
1430{
1432}
1433
1441QAbstractSocket::PauseModes QAbstractSocket::pauseMode() const
1442{
1443 return d_func()->pauseMode;
1444}
1445
1446
1461void QAbstractSocket::setPauseMode(PauseModes pauseMode)
1462{
1463 d_func()->pauseMode = pauseMode;
1464}
1465
1487{
1488 Q_D(QAbstractSocket);
1489 return d->bind(address, port, mode);
1490}
1491
1492bool QAbstractSocketPrivate::bind(const QHostAddress &address, quint16 port, QAbstractSocket::BindMode mode)
1493{
1494 Q_Q(QAbstractSocket);
1495
1496 // now check if the socket engine is initialized and to the right type
1497 if (!socketEngine || !socketEngine->isValid()) {
1498 QHostAddress nullAddress;
1499 resolveProxy(nullAddress.toString(), port);
1500
1501 QAbstractSocket::NetworkLayerProtocol protocol = address.protocol();
1503 protocol = nullAddress.protocol();
1504
1505 if (!initSocketLayer(protocol))
1506 return false;
1507 }
1508
1510#ifdef Q_OS_UNIX
1513 else
1515#endif
1516#ifdef Q_OS_WIN
1519 else
1523 else
1525#endif
1526 }
1529
1530 if (!result) {
1532 return false;
1533 }
1534
1538
1539 emit q->stateChanged(state);
1540 // A slot attached to stateChanged() signal can break our invariant:
1541 // by closing the socket it will reset its socket engine - thus we
1542 // have additional check (isValid()) ...
1543 if (q->isValid() && socketType == QAbstractSocket::UdpSocket)
1545 return true;
1546}
1547
1570#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
1571bool QAbstractSocket::bind(quint16 port, BindMode mode)
1572{
1573 return bind(QHostAddress::Any, port, mode);
1574}
1575#endif
1576
1587{
1588 return d_func()->socketEngine ? d_func()->socketEngine->isValid() : isOpen();
1589}
1590
1615 OpenMode openMode,
1616 NetworkLayerProtocol protocol)
1617{
1618 Q_D(QAbstractSocket);
1619#if defined(QABSTRACTSOCKET_DEBUG)
1620 qDebug("QAbstractSocket::connectToHost(\"%s\", %i, %i)...", qPrintable(hostName), port,
1621 (int) openMode);
1622#endif
1623
1624 if (d->state == ConnectedState || d->state == ConnectingState
1625 || d->state == ClosingState || d->state == HostLookupState) {
1626 qWarning("QAbstractSocket::connectToHost() called when already looking up or connecting/connected to \"%s\"", qPrintable(hostName));
1627 d->setErrorAndEmit(OperationError, tr("Trying to connect while connection is in progress"));
1628 return;
1629 }
1630
1631 d->preferredNetworkLayerProtocol = protocol;
1632 d->hostName = hostName;
1633 d->port = port;
1634 d->setReadChannelCount(0);
1635 d->setWriteChannelCount(0);
1636 d->abortCalled = false;
1637 d->pendingClose = false;
1638 if (d->state != BoundState) {
1639 d->state = UnconnectedState;
1640 d->localPort = 0;
1641 d->localAddress.clear();
1642 }
1643 d->peerPort = 0;
1644 d->peerAddress.clear();
1645 d->peerName = hostName;
1646 if (d->hostLookupId != -1) {
1647 QHostInfo::abortHostLookup(d->hostLookupId);
1648 d->hostLookupId = -1;
1649 }
1650
1651#ifndef QT_NO_NETWORKPROXY
1652 // Get the proxy information
1653 d->resolveProxy(hostName, port);
1654 if (d->proxyInUse.type() == QNetworkProxy::DefaultProxy) {
1655 // failed to setup the proxy
1656 d->setErrorAndEmit(UnsupportedSocketOperationError,
1657 tr("Operation on socket is not supported"));
1658 return;
1659 }
1660#endif
1661
1662 // Sync up with error string, which open() shall clear.
1663 d->socketError = UnknownSocketError;
1665 d->isBuffered = false;
1666 else if (!d_func()->isBuffered)
1668
1670 d->readChannelCount = d->writeChannelCount = 0;
1671
1672 d->state = HostLookupState;
1673 emit stateChanged(d->state);
1674
1675 QHostAddress temp;
1676 if (temp.setAddress(hostName)) {
1678 info.setAddresses(QList<QHostAddress>() << temp);
1679 d->_q_startConnecting(info);
1680#ifndef QT_NO_NETWORKPROXY
1681 } else if (d->proxyInUse.capabilities() & QNetworkProxy::HostNameLookupCapability) {
1682 // the proxy supports connection by name, so use it
1683 d->startConnectingByName(hostName);
1684 return;
1685#endif
1686 } else {
1687 if (d->threadData.loadRelaxed()->hasEventDispatcher()) {
1688 // this internal API for QHostInfo either immediately gives us the desired
1689 // QHostInfo from cache or later calls the _q_startConnecting slot.
1690 bool immediateResultValid = false;
1691 QHostInfo hostInfo = qt_qhostinfo_lookup(hostName,
1692 this,
1693 SLOT(_q_startConnecting(QHostInfo)),
1694 &immediateResultValid,
1695 &d->hostLookupId);
1696 if (immediateResultValid) {
1697 d->hostLookupId = -1;
1698 d->_q_startConnecting(hostInfo);
1699 }
1700 }
1701 }
1702
1703#if defined(QABSTRACTSOCKET_DEBUG)
1704 qDebug("QAbstractSocket::connectToHost(\"%s\", %i) == %s%s", hostName.toLatin1().constData(), port,
1705 (d->state == ConnectedState) ? "true" : "false",
1706 (d->state == ConnectingState || d->state == HostLookupState)
1707 ? " (connection in progress)" : "");
1708#endif
1709}
1710
1716 OpenMode openMode)
1717{
1718#if defined(QABSTRACTSOCKET_DEBUG)
1719 qDebug("QAbstractSocket::connectToHost([%s], %i, %i)...",
1720 address.toString().toLatin1().constData(), port, (int) openMode);
1721#endif
1722 connectToHost(address.toString(), port, openMode);
1723}
1724
1733{
1734 const qint64 pendingBytes = QIODevice::bytesToWrite();
1735#if defined(QABSTRACTSOCKET_DEBUG)
1736 qDebug("QAbstractSocket::bytesToWrite() == %lld", pendingBytes);
1737#endif
1738 return pendingBytes;
1739}
1740
1747{
1748 Q_D(const QAbstractSocket);
1749 qint64 available = QIODevice::bytesAvailable();
1750
1751 if (!d->isBuffered && d->socketEngine && d->socketEngine->isValid())
1752 available += d->socketEngine->bytesAvailable();
1753
1754#if defined(QABSTRACTSOCKET_DEBUG)
1755 qDebug("QAbstractSocket::bytesAvailable() == %lld", available);
1756#endif
1757 return available;
1758}
1759
1767{
1768 Q_D(const QAbstractSocket);
1769 return d->localPort;
1770}
1771
1783{
1784 Q_D(const QAbstractSocket);
1785 return d->localAddress;
1786}
1787
1795{
1796 Q_D(const QAbstractSocket);
1797 return d->peerPort;
1798}
1799
1807{
1808 Q_D(const QAbstractSocket);
1809 return d->peerAddress;
1810}
1811
1819{
1820 Q_D(const QAbstractSocket);
1821 return d->peerName.isEmpty() ? d->hostName : d->peerName;
1822}
1823
1837{
1838 Q_D(const QAbstractSocket);
1839 return d->cachedSocketDescriptor;
1840}
1841
1856 OpenMode openMode)
1857{
1858 Q_D(QAbstractSocket);
1859
1860 d->resetSocketLayer();
1861 d->setReadChannelCount(0);
1862 d->setWriteChannelCount(0);
1864 if (!d->socketEngine) {
1865 d->setError(UnsupportedSocketOperationError, tr("Operation on socket is not supported"));
1866 return false;
1867 }
1868 bool result = d->socketEngine->initialize(socketDescriptor, socketState);
1869 if (!result) {
1870 d->setError(d->socketEngine->error(), d->socketEngine->errorString());
1871 return false;
1872 }
1873
1874 // Sync up with error string, which open() shall clear.
1875 d->socketError = UnknownSocketError;
1876 if (d->threadData.loadRelaxed()->hasEventDispatcher())
1877 d->socketEngine->setReceiver(d);
1878
1880
1881 if (socketState == ConnectedState) {
1882 if (isReadable()) {
1883 const int inboundStreamCount = d->socketEngine->inboundStreamCount();
1884 d->setReadChannelCount(qMax(1, inboundStreamCount));
1885 if (inboundStreamCount == 0)
1886 d->readChannelCount = 0;
1887 }
1888 if (isWritable()) {
1889 const int outboundStreamCount = d->socketEngine->outboundStreamCount();
1890 d->setWriteChannelCount(qMax(1, outboundStreamCount));
1891 if (outboundStreamCount == 0)
1892 d->writeChannelCount = 0;
1893 }
1894 } else {
1895 d->readChannelCount = d->writeChannelCount = 0;
1896 }
1897
1898 if (d->state != socketState) {
1899 d->state = socketState;
1900 emit stateChanged(d->state);
1901 }
1902
1903 d->pendingClose = false;
1904 d->socketEngine->setReadNotificationEnabled(true);
1905 d->localPort = d->socketEngine->localPort();
1906 d->peerPort = d->socketEngine->peerPort();
1907 d->localAddress = d->socketEngine->localAddress();
1908 d->peerAddress = d->socketEngine->peerAddress();
1909 d->cachedSocketDescriptor = socketDescriptor;
1910
1911 return true;
1912}
1913
1925{
1926 if (!d_func()->socketEngine)
1927 return;
1928
1929 switch (option) {
1930 case LowDelayOption:
1931 d_func()->socketEngine->setOption(QAbstractSocketEngine::LowDelayOption, value.toInt());
1932 break;
1933
1934 case KeepAliveOption:
1935 d_func()->socketEngine->setOption(QAbstractSocketEngine::KeepAliveOption, value.toInt());
1936 break;
1937
1938 case MulticastTtlOption:
1939 d_func()->socketEngine->setOption(QAbstractSocketEngine::MulticastTtlOption, value.toInt());
1940 break;
1941
1943 d_func()->socketEngine->setOption(QAbstractSocketEngine::MulticastLoopbackOption, value.toInt());
1944 break;
1945
1947 d_func()->socketEngine->setOption(QAbstractSocketEngine::TypeOfServiceOption, value.toInt());
1948 break;
1949
1951 d_func()->socketEngine->setOption(QAbstractSocketEngine::SendBufferSocketOption, value.toInt());
1952 break;
1953
1955 d_func()->socketEngine->setOption(QAbstractSocketEngine::ReceiveBufferSocketOption, value.toInt());
1956 break;
1957
1959 d_func()->socketEngine->setOption(QAbstractSocketEngine::PathMtuInformation, value.toInt());
1960 break;
1961 }
1962}
1963
1971{
1972 if (!d_func()->socketEngine)
1973 return QVariant();
1974
1975 int ret = -1;
1976 switch (option) {
1977 case LowDelayOption:
1978 ret = d_func()->socketEngine->option(QAbstractSocketEngine::LowDelayOption);
1979 break;
1980
1981 case KeepAliveOption:
1982 ret = d_func()->socketEngine->option(QAbstractSocketEngine::KeepAliveOption);
1983 break;
1984
1985 case MulticastTtlOption:
1986 ret = d_func()->socketEngine->option(QAbstractSocketEngine::MulticastTtlOption);
1987 break;
1989 ret = d_func()->socketEngine->option(QAbstractSocketEngine::MulticastLoopbackOption);
1990 break;
1991
1993 ret = d_func()->socketEngine->option(QAbstractSocketEngine::TypeOfServiceOption);
1994 break;
1995
1997 ret = d_func()->socketEngine->option(QAbstractSocketEngine::SendBufferSocketOption);
1998 break;
1999
2001 ret = d_func()->socketEngine->option(QAbstractSocketEngine::ReceiveBufferSocketOption);
2002 break;
2003
2005 ret = d_func()->socketEngine->option(QAbstractSocketEngine::PathMtuInformation);
2006 break;
2007 }
2008 if (ret == -1)
2009 return QVariant();
2010 else
2011 return QVariant(ret);
2012}
2013
2040{
2041 Q_D(QAbstractSocket);
2042#if defined (QABSTRACTSOCKET_DEBUG)
2043 qDebug("QAbstractSocket::waitForConnected(%i)", msecs);
2044#endif
2045
2046 if (state() == ConnectedState) {
2047#if defined (QABSTRACTSOCKET_DEBUG)
2048 qDebug("QAbstractSocket::waitForConnected(%i) already connected", msecs);
2049#endif
2050 return true;
2051 }
2052
2053 bool wasPendingClose = d->pendingClose;
2054 d->pendingClose = false;
2055 QElapsedTimer stopWatch;
2056 stopWatch.start();
2057
2058 if (d->state == HostLookupState) {
2059#if defined (QABSTRACTSOCKET_DEBUG)
2060 qDebug("QAbstractSocket::waitForConnected(%i) doing host name lookup", msecs);
2061#endif
2062 QHostInfo::abortHostLookup(d->hostLookupId);
2063 d->hostLookupId = -1;
2064 QHostAddress temp;
2065 if (temp.setAddress(d->hostName)) {
2067 info.setAddresses(QList<QHostAddress>() << temp);
2068 d->_q_startConnecting(info);
2069 } else {
2070 d->_q_startConnecting(QHostInfo::fromName(d->hostName));
2071 }
2072 }
2073 if (state() == UnconnectedState)
2074 return false; // connect not im progress anymore!
2075
2076 int connectTimeout = DefaultConnectTimeout;
2077 bool timedOut = true;
2078#if defined (QABSTRACTSOCKET_DEBUG)
2079 int attempt = 1;
2080#endif
2081 while (state() == ConnectingState && (msecs == -1 || stopWatch.elapsed() < msecs)) {
2082 int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
2083 if (msecs != -1 && timeout > connectTimeout)
2084 timeout = connectTimeout;
2085#if defined (QABSTRACTSOCKET_DEBUG)
2086 qDebug("QAbstractSocket::waitForConnected(%i) waiting %.2f secs for connection attempt #%i",
2087 msecs, timeout / 1000.0, attempt++);
2088#endif
2089 timedOut = false;
2090
2091 if (d->socketEngine && d->socketEngine->waitForWrite(timeout, &timedOut) && !timedOut) {
2092 d->_q_testConnection();
2093 } else {
2094 d->_q_connectToNextAddress();
2095 }
2096 }
2097
2098 if ((timedOut && state() != ConnectedState) || state() == ConnectingState) {
2099 d->setError(SocketTimeoutError, tr("Socket operation timed out"));
2100 d->state = UnconnectedState;
2101 emit stateChanged(d->state);
2102 d->resetSocketLayer();
2103 }
2104
2105#if defined (QABSTRACTSOCKET_DEBUG)
2106 qDebug("QAbstractSocket::waitForConnected(%i) == %s", msecs,
2107 state() == ConnectedState ? "true" : "false");
2108#endif
2109 if (state() != ConnectedState)
2110 return false;
2111 if (wasPendingClose)
2113 return true;
2114}
2115
2132{
2133 Q_D(QAbstractSocket);
2134#if defined (QABSTRACTSOCKET_DEBUG)
2135 qDebug("QAbstractSocket::waitForReadyRead(%i)", msecs);
2136#endif
2137
2138 // require calling connectToHost() before waitForReadyRead()
2139 if (state() == UnconnectedState) {
2140 /* If all you have is a QIODevice pointer to an abstractsocket, you cannot check
2141 this, so you cannot avoid this warning. */
2142// qWarning("QAbstractSocket::waitForReadyRead() is not allowed in UnconnectedState");
2143 return false;
2144 }
2145
2146 QElapsedTimer stopWatch;
2147 stopWatch.start();
2148
2149 // handle a socket in connecting state
2150 if (state() == HostLookupState || state() == ConnectingState) {
2151 if (!waitForConnected(msecs))
2152 return false;
2153 }
2154
2155 do {
2156 if (state() != ConnectedState && state() != BoundState)
2157 return false;
2158 Q_ASSERT(d->socketEngine);
2159
2160 bool readyToRead = false;
2161 bool readyToWrite = false;
2162 if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, !d->writeBuffer.isEmpty(),
2163 qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) {
2164#if defined (QABSTRACTSOCKET_DEBUG)
2165 qDebug("QAbstractSocket::waitForReadyRead(%i) failed (%i, %s)",
2166 msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData());
2167#endif
2168 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
2169 if (d->socketError != SocketTimeoutError)
2170 close();
2171 return false;
2172 }
2173
2174 if (readyToRead) {
2175 if (d->canReadNotification())
2176 return true;
2177 }
2178
2179 if (readyToWrite)
2180 d->canWriteNotification();
2181 } while (msecs == -1 || qt_subtract_from_timeout(msecs, stopWatch.elapsed()) > 0);
2182 return false;
2183}
2184
2202{
2203 Q_D(QAbstractSocket);
2204#if defined (QABSTRACTSOCKET_DEBUG)
2205 qDebug("QAbstractSocket::waitForBytesWritten(%i)", msecs);
2206#endif
2207
2208 // require calling connectToHost() before waitForBytesWritten()
2209 if (state() == UnconnectedState) {
2210 qWarning("QAbstractSocket::waitForBytesWritten() is not allowed in UnconnectedState");
2211 return false;
2212 }
2213
2214 if (d->writeBuffer.isEmpty())
2215 return false;
2216
2217 QElapsedTimer stopWatch;
2218 stopWatch.start();
2219
2220 // handle a socket in connecting state
2221 if (state() == HostLookupState || state() == ConnectingState) {
2222 if (!waitForConnected(msecs))
2223 return false;
2224 }
2225
2226 forever {
2227 bool readyToRead = false;
2228 bool readyToWrite = false;
2229 if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite,
2230 !d->readBufferMaxSize || d->buffer.size() < d->readBufferMaxSize,
2231 !d->writeBuffer.isEmpty(),
2232 qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) {
2233#if defined (QABSTRACTSOCKET_DEBUG)
2234 qDebug("QAbstractSocket::waitForBytesWritten(%i) failed (%i, %s)",
2235 msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData());
2236#endif
2237 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
2238 if (d->socketError != SocketTimeoutError)
2239 close();
2240 return false;
2241 }
2242
2243 if (readyToRead) {
2244#if defined (QABSTRACTSOCKET_DEBUG)
2245 qDebug("QAbstractSocket::waitForBytesWritten calls canReadNotification");
2246#endif
2247 d->canReadNotification();
2248 }
2249
2250
2251 if (readyToWrite) {
2252 if (d->canWriteNotification()) {
2253#if defined (QABSTRACTSOCKET_DEBUG)
2254 qDebug("QAbstractSocket::waitForBytesWritten returns true");
2255#endif
2256 return true;
2257 }
2258 }
2259
2260 if (state() != ConnectedState)
2261 return false;
2262 }
2263 return false;
2264}
2265
2287{
2288 Q_D(QAbstractSocket);
2289
2290 // require calling connectToHost() before waitForDisconnected()
2291 if (state() == UnconnectedState) {
2292 qWarning("QAbstractSocket::waitForDisconnected() is not allowed in UnconnectedState");
2293 return false;
2294 }
2295
2296 QElapsedTimer stopWatch;
2297 stopWatch.start();
2298
2299 // handle a socket in connecting state
2300 if (state() == HostLookupState || state() == ConnectingState) {
2301 if (!waitForConnected(msecs))
2302 return false;
2303 if (state() == UnconnectedState)
2304 return true;
2305 }
2306
2307 forever {
2308 bool readyToRead = false;
2309 bool readyToWrite = false;
2310 if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, state() == ConnectedState,
2311 !d->writeBuffer.isEmpty(),
2312 qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) {
2313#if defined (QABSTRACTSOCKET_DEBUG)
2314 qDebug("QAbstractSocket::waitForReadyRead(%i) failed (%i, %s)",
2315 msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData());
2316#endif
2317 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
2318 if (d->socketError != SocketTimeoutError)
2319 close();
2320 return false;
2321 }
2322
2323 if (readyToRead)
2324 d->canReadNotification();
2325 if (readyToWrite)
2326 d->canWriteNotification();
2327
2328 if (state() == UnconnectedState)
2329 return true;
2330 }
2331 return false;
2332}
2333
2342{
2343 Q_D(QAbstractSocket);
2344#if defined (QABSTRACTSOCKET_DEBUG)
2345 qDebug("QAbstractSocket::abort()");
2346#endif
2347 d->setWriteChannelCount(0);
2348 d->abortCalled = true;
2349 close();
2350}
2351
2355{
2356 return true;
2357}
2358
2374{
2375 return d_func()->flush();
2376}
2377
2381{
2382 Q_D(QAbstractSocket);
2383
2384 // if we're not connected, return -1 indicating EOF
2385 if (!d->socketEngine || !d->socketEngine->isValid() || d->state != QAbstractSocket::ConnectedState)
2386 return maxSize ? qint64(-1) : qint64(0);
2387
2388 qint64 readBytes = (maxSize && !d->isBuffered) ? d->socketEngine->read(data, maxSize)
2389 : qint64(0);
2390 if (readBytes == -2) {
2391 // -2 from the engine means no bytes available (EAGAIN) so read more later
2392 readBytes = 0;
2393 }
2394 if (readBytes < 0) {
2395 d->setError(d->socketEngine->error(), d->socketEngine->errorString());
2396 d->resetSocketLayer();
2398 } else {
2399 // Only do this when there was no error
2400 d->hasPendingData = false;
2401 d->socketEngine->setReadNotificationEnabled(true);
2402 }
2403
2404#if defined (QABSTRACTSOCKET_DEBUG)
2405 qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld [engine]", data,
2406 QtDebugUtils::toPrintable(data, readBytes, 32).constData(), maxSize, readBytes);
2407#endif
2408 return readBytes;
2409}
2410
2414{
2415 return QIODevice::readLineData(data, maxlen);
2416}
2417
2421{
2422 Q_D(QAbstractSocket);
2424 || (!d->socketEngine && d->socketType != TcpSocket && !d->isBuffered)) {
2425 d->setError(UnknownSocketError, tr("Socket is not connected"));
2426 return -1;
2427 }
2428
2429 if (!d->isBuffered && d->socketType == TcpSocket
2430 && d->socketEngine && d->writeBuffer.isEmpty()) {
2431 // This code is for the new Unbuffered QTcpSocket use case
2432 qint64 written = size ? d->socketEngine->write(data, size) : Q_INT64_C(0);
2433 if (written < 0) {
2434 d->setError(d->socketEngine->error(), d->socketEngine->errorString());
2435 } else if (written < size) {
2436 // Buffer what was not written yet
2437 d->writeBuffer.append(data + written, size - written);
2438 written = size;
2439 d->socketEngine->setWriteNotificationEnabled(true);
2440 }
2441
2442#if defined (QABSTRACTSOCKET_DEBUG)
2443 qDebug("QAbstractSocket::writeData(%p \"%s\", %lli) == %lli", data,
2444 QtDebugUtils::toPrintable(data, size, 32).constData(), size, written);
2445#endif
2446 return written; // written = actually written + what has been buffered
2447 } else if (!d->isBuffered && d->socketType != TcpSocket) {
2448 // This is for a QUdpSocket that was connect()ed
2449 qint64 written = d->socketEngine->write(data, size);
2450 if (written < 0)
2451 d->setError(d->socketEngine->error(), d->socketEngine->errorString());
2452
2453#if defined (QABSTRACTSOCKET_DEBUG)
2454 qDebug("QAbstractSocket::writeData(%p \"%s\", %lli) == %lli", data,
2455 QtDebugUtils::toPrintable(data, size, 32).constData(), size, written);
2456#endif
2457 if (written >= 0)
2458 d->emitBytesWritten(written);
2459 return written;
2460 }
2461
2462 // This is the code path for normal buffered QTcpSocket or
2463 // unbuffered QTcpSocket when there was already something in the
2464 // write buffer and therefore we could not do a direct engine write.
2465 // We just write to our write buffer and enable the write notifier
2466 // The write notifier then flush()es the buffer.
2467
2468 d->write(data, size);
2469 qint64 written = size;
2470
2471 if (d->socketEngine && !d->writeBuffer.isEmpty())
2472 d->socketEngine->setWriteNotificationEnabled(true);
2473
2474#if defined (QABSTRACTSOCKET_DEBUG)
2475 qDebug("QAbstractSocket::writeData(%p \"%s\", %lli) == %lli", data,
2476 QtDebugUtils::toPrintable(data, size, 32).constData(), size, written);
2477#endif
2478 return written;
2479}
2480
2497{
2498 Q_D(QAbstractSocket);
2499 d->localPort = port;
2500}
2501
2519{
2520 Q_D(QAbstractSocket);
2521 d->localAddress = address;
2522}
2523
2538{
2539 Q_D(QAbstractSocket);
2540 d->peerPort = port;
2541}
2542
2557{
2558 Q_D(QAbstractSocket);
2559 d->peerAddress = address;
2560}
2561
2575{
2576 Q_D(QAbstractSocket);
2577 d->peerName = name;
2578}
2579
2590{
2591 Q_D(QAbstractSocket);
2592#if defined(QABSTRACTSOCKET_DEBUG)
2593 qDebug("QAbstractSocket::close()");
2594#endif
2596 if (d->state != UnconnectedState)
2598}
2599
2609{
2610 Q_D(QAbstractSocket);
2611#if defined(QABSTRACTSOCKET_DEBUG)
2612 qDebug("QAbstractSocket::disconnectFromHost()");
2613#endif
2614
2615 if (d->state == UnconnectedState) {
2616#if defined(QABSTRACTSOCKET_DEBUG)
2617 qDebug("QAbstractSocket::disconnectFromHost() was called on an unconnected socket");
2618#endif
2619 return;
2620 }
2621
2622 if (!d->abortCalled && (d->state == ConnectingState || d->state == HostLookupState)) {
2623#if defined(QABSTRACTSOCKET_DEBUG)
2624 qDebug("QAbstractSocket::disconnectFromHost() but we're still connecting");
2625#endif
2626 d->pendingClose = true;
2627 return;
2628 }
2629
2630 // Disable and delete read notification
2631 if (d->socketEngine)
2632 d->socketEngine->setReadNotificationEnabled(false);
2633
2634 if (d->abortCalled) {
2635#if defined(QABSTRACTSOCKET_DEBUG)
2636 qDebug("QAbstractSocket::disconnectFromHost() aborting immediately");
2637#endif
2638 if (d->state == HostLookupState) {
2639 QHostInfo::abortHostLookup(d->hostLookupId);
2640 d->hostLookupId = -1;
2641 }
2642 } else {
2643 // Perhaps emit closing()
2644 if (d->state != ClosingState) {
2645 d->state = ClosingState;
2646#if defined(QABSTRACTSOCKET_DEBUG)
2647 qDebug("QAbstractSocket::disconnectFromHost() emits stateChanged()(ClosingState)");
2648#endif
2649 emit stateChanged(d->state);
2650 } else {
2651#if defined(QABSTRACTSOCKET_DEBUG)
2652 qDebug("QAbstractSocket::disconnectFromHost() return from delayed close");
2653#endif
2654 }
2655
2656 // Wait for pending data to be written.
2657 if (d->socketEngine && d->socketEngine->isValid() && (!d->allWriteBuffersEmpty()
2658 || d->socketEngine->bytesToWrite() > 0)) {
2659 d->socketEngine->setWriteNotificationEnabled(true);
2660
2661#if defined(QABSTRACTSOCKET_DEBUG)
2662 qDebug("QAbstractSocket::disconnectFromHost() delaying disconnect");
2663#endif
2664 return;
2665 } else {
2666#if defined(QABSTRACTSOCKET_DEBUG)
2667 qDebug("QAbstractSocket::disconnectFromHost() disconnecting immediately");
2668#endif
2669 }
2670 }
2671
2672 SocketState previousState = d->state;
2673 d->resetSocketLayer();
2674 d->state = UnconnectedState;
2675 emit stateChanged(d->state);
2676 emit readChannelFinished(); // we got an EOF
2677
2678 // only emit disconnected if we were connected before
2679 if (previousState == ConnectedState || previousState == ClosingState)
2681
2682 d->localPort = 0;
2683 d->peerPort = 0;
2684 d->localAddress.clear();
2685 d->peerAddress.clear();
2686 d->peerName.clear();
2687 d->setWriteChannelCount(0);
2688
2689#if defined(QABSTRACTSOCKET_DEBUG)
2690 qDebug("QAbstractSocket::disconnectFromHost() disconnected!");
2691#endif
2692
2693}
2694
2706{
2707 return d_func()->readBufferMaxSize;
2708}
2709
2733{
2734 Q_D(QAbstractSocket);
2735
2736 if (d->readBufferMaxSize == size)
2737 return;
2738 d->readBufferMaxSize = size;
2739
2740 // Do not change the notifier unless we are connected.
2741 if (d->socketEngine && d->state == QAbstractSocket::ConnectedState) {
2742 // Ensure that the read notification is enabled if we've now got
2743 // room in the read buffer.
2744 d->socketEngine->setReadNotificationEnabled(size == 0 || d->buffer.size() < size);
2745 }
2746}
2747
2754{
2755 return d_func()->state;
2756}
2757
2764{
2765 d_func()->state = state;
2766}
2767
2774{
2775 return d_func()->socketType;
2776}
2777
2784{
2785 return d_func()->socketError;
2786}
2787
2794{
2795 d_func()->socketError = socketError;
2796}
2797
2798#ifndef QT_NO_NETWORKPROXY
2819{
2820 Q_D(QAbstractSocket);
2821 d->proxy = networkProxy;
2822}
2823
2834{
2835 Q_D(const QAbstractSocket);
2836 return d->proxy;
2837}
2838
2851{
2852 Q_D(const QAbstractSocket);
2853 return d->protocolTag;
2854}
2855
2865{
2866 Q_D(QAbstractSocket);
2867 d->protocolTag = tag;
2868}
2869
2870#endif // QT_NO_NETWORKPROXY
2871
2872#ifndef QT_NO_DEBUG_STREAM
2874{
2875 QDebugStateSaver saver(debug);
2876 debug.resetFormat().nospace();
2877 switch (error) {
2879 debug << "QAbstractSocket::ConnectionRefusedError";
2880 break;
2882 debug << "QAbstractSocket::RemoteHostClosedError";
2883 break;
2885 debug << "QAbstractSocket::HostNotFoundError";
2886 break;
2888 debug << "QAbstractSocket::SocketAccessError";
2889 break;
2891 debug << "QAbstractSocket::SocketResourceError";
2892 break;
2894 debug << "QAbstractSocket::SocketTimeoutError";
2895 break;
2897 debug << "QAbstractSocket::DatagramTooLargeError";
2898 break;
2900 debug << "QAbstractSocket::NetworkError";
2901 break;
2903 debug << "QAbstractSocket::AddressInUseError";
2904 break;
2906 debug << "QAbstractSocket::SocketAddressNotAvailableError";
2907 break;
2909 debug << "QAbstractSocket::UnsupportedSocketOperationError";
2910 break;
2912 debug << "QAbstractSocket::UnfinishedSocketOperationError";
2913 break;
2915 debug << "QAbstractSocket::ProxyAuthenticationRequiredError";
2916 break;
2918 debug << "QAbstractSocket::UnknownSocketError";
2919 break;
2921 debug << "QAbstractSocket::ProxyConnectionRefusedError";
2922 break;
2924 debug << "QAbstractSocket::ProxyConnectionClosedError";
2925 break;
2927 debug << "QAbstractSocket::ProxyConnectionTimeoutError";
2928 break;
2930 debug << "QAbstractSocket::ProxyNotFoundError";
2931 break;
2933 debug << "QAbstractSocket::ProxyProtocolError";
2934 break;
2935 default:
2936 debug << "QAbstractSocket::SocketError(" << int(error) << ')';
2937 break;
2938 }
2939 return debug;
2940}
2941
2943{
2944 QDebugStateSaver saver(debug);
2945 debug.resetFormat().nospace();
2946 switch (state) {
2948 debug << "QAbstractSocket::UnconnectedState";
2949 break;
2951 debug << "QAbstractSocket::HostLookupState";
2952 break;
2954 debug << "QAbstractSocket::ConnectingState";
2955 break;
2957 debug << "QAbstractSocket::ConnectedState";
2958 break;
2960 debug << "QAbstractSocket::BoundState";
2961 break;
2963 debug << "QAbstractSocket::ListeningState";
2964 break;
2966 debug << "QAbstractSocket::ClosingState";
2967 break;
2968 default:
2969 debug << "QAbstractSocket::SocketState(" << int(state) << ')';
2970 break;
2971 }
2972 return debug;
2973}
2974#endif
2975
2977
2978#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 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:122
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
qint64 elapsed() const noexcept
Returns the number of milliseconds since this QElapsedTimer was last started.
void start() noexcept
Starts this timer.
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().
static QHostInfo fromName(const QString &name)
Looks up the IP address(es) for the given host name.
QList< QHostAddress > addresses() const
Returns the list of IP addresses associated with hostName().
int lookupId() const
Returns the ID of this lookup.
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()
constexpr const char * constData() const noexcept
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
value_type takeFirst()
Definition qlist.h:549
qsizetype count() const noexcept
Definition qlist.h:387
void clear()
Definition qlist.h:417
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:202
\inmodule QtCore
Definition qobject.h:90
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3099
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QByteArray toLatin1() const &
Definition qstring.h:559
\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:208
void stop()
Stops the timer.
Definition qtimer.cpp:226
T * data() noexcept
\inmodule QtCore
Definition qvariant.h:64
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:29
@ QueuedConnection
@ DirectConnection
static const int 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)
#define forever
Definition qforeach.h:78
QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id)
int qt_subtract_from_timeout(int timeout, int elapsed)
#define qDebug
[1]
Definition qlogging.h:160
#define qWarning
Definition qlogging.h:162
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:1363
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLenum mode
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLbitfield GLuint64 timeout
[4]
GLenum GLuint buffer
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
GLenum query
GLuint writeBuffer
GLuint GLuint64EXT address
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
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:1391
#define tr(X)
#define emit
unsigned short quint16
Definition qtypes.h:43
long long qint64
Definition qtypes.h:55
#define Q_INT64_C(c)
Definition qtypes.h:52
ptrdiff_t qintptr
Definition qtypes.h:71
QFileInfo info(fileName)
[8]
QTcpSocket * socket
[1]
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...
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent