1 #include <QNetworkAddressEntry>
2 #include <QReadWriteLock>
3 #include <QWriteLocker>
14 if (x.protocol() == QAbstractSocket::IPv6Protocol)
15 return "[" + x.toString().toLower() +
"]";
16 return x.toString().toLower();
20 #define LOC QString("ServerPool: ")
28 QHostAddress::parseSubnet(
"169.254.0.0/16");
30 QHostAddress::parseSubnet(
"fe80::/10");
38 QNetworkAddressEntry
host()
46 static bool contains(
const QNetworkAddressEntry&
host,
const QHostAddress& addr)
48 if (addr.protocol() == QAbstractSocket::IPv6Protocol &&
50 host.ip().scopeId() != addr.scopeId())
54 return addr.isInSubnet(
host.ip(),
host.prefixLength());
61 : QTcpServer(parent), m_serverType(
type)
79 QReadLocker rlock(&
naLock);
85 QWriteLocker wlock(&
naLock);
91 QNetworkAddressEntry entry;
92 entry.setIp(QHostAddress(QHostAddress::AnyIPv4));
94 entry.setIp(QHostAddress(QHostAddress::AnyIPv6));
104 bool v4IsSet = config_v4.isNull();
109 bool v6IsSet = config_v6.isNull();
113 QList<QNetworkInterface> IFs = QNetworkInterface::allInterfaces();
114 for (
const auto & qni : std::as_const(IFs))
116 if ((qni.flags() & QNetworkInterface::IsRunning) == 0)
119 QList<QNetworkAddressEntry> IPs = qni.addressEntries();
123 for (
auto qnai = IPs.begin(); qnai != IPs.end(); ++qnai)
125 QHostAddress ip = qnai->ip();
126 if (ip.protocol() == QAbstractSocket::IPv4Protocol)
132 if (!config_v4.isNull() && (ip == config_v4))
135 LOG(VB_GENERAL, LOG_DEBUG,
136 QString(
"Adding BackendServerIP to address list."));
142 else if (ip == QHostAddress::LocalHost)
145 LOG(VB_GENERAL, LOG_DEBUG,
146 QString(
"Adding IPv4 loopback to address list."));
148 if (!v4IsSet && (config_v4 == ip))
152 else if (ip.isInSubnet(
kLinkLocal) && allowLinkLocal)
157 LOG(VB_GENERAL, LOG_DEBUG,
158 QString(
"Adding link-local '%1' to address list.")
163 else if (config_v4.isNull())
167 static QPair<QHostAddress, int>
168 s_privNet1 = QHostAddress::parseSubnet(
"10.0.0.0/8");
169 static QPair<QHostAddress, int>
170 s_privNet2 = QHostAddress::parseSubnet(
"172.16.0.0/12");
171 static QPair<QHostAddress, int>
172 s_privNet3 = QHostAddress::parseSubnet(
"192.168.0.0/16");
174 if (ip.isInSubnet(s_privNet1) || ip.isInSubnet(s_privNet2) ||
175 ip.isInSubnet(s_privNet3))
177 LOG(VB_GENERAL, LOG_DEBUG,
178 QString(
"Adding '%1' to address list.")
184 LOG(VB_GENERAL, LOG_DEBUG,
185 QString(
"Adding link-local '%1' to address list.")
191 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Skipping "
192 "non-private address during IPv4 autoselection: %1")
199 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Skipping address: %1")
209 ip.setScopeId(qni.name());
217 if ((!config_v6.isNull()) && (ip == config_v6))
220 LOG(VB_GENERAL, LOG_DEBUG,
221 QString(
"Adding BackendServerIP6 to address list."));
226 else if (ip == QHostAddress::LocalHostIPv6)
229 LOG(VB_GENERAL, LOG_DEBUG,
230 QString(
"Adding IPv6 loopback to address list."));
232 if (!v6IsSet && (config_v6 == ip))
236 else if (ip.isInSubnet(
kLinkLocal6) && allowLinkLocal)
241 LOG(VB_GENERAL, LOG_DEBUG,
242 QString(
"Adding link-local '%1' to address list.")
243 .arg(ip.toString()));
247 else if (config_v6.isNull())
251 LOG(VB_GENERAL, LOG_DEBUG,
252 QString(
"Adding link-local '%1' to address list.")
257 LOG(VB_GENERAL, LOG_DEBUG,
258 QString(
"Adding '%1' to address list.")
267 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Skipping address: %1")
274 if (!v4IsSet && (config_v4 != QHostAddress::LocalHost)
277 LOG(VB_GENERAL, LOG_CRIT,
LOC + QString(
"Host is configured to listen "
278 "on %1, but address is not used on any local network "
279 "interfaces.").arg(config_v4.toString()));
282 if (!v6IsSet && (config_v6 != QHostAddress::LocalHostIPv6)
285 LOG(VB_GENERAL, LOG_CRIT,
LOC + QString(
"Host is configured to listen "
286 "on %1, but address is not used on any local network "
287 "interfaces.").arg(
prettyip(config_v6)));
307 QList<QHostAddress> alist;
316 QReadLocker rlock(&
naLock);
318 QList<QHostAddress> alist;
319 for (
const auto & nae : std::as_const(
naList_4))
320 if (!alist.contains(nae.ip()))
329 QReadLocker rlock(&
naLock);
331 QList<QHostAddress> alist;
332 for (
const auto & nae : std::as_const(
naList_6))
333 if (!alist.contains(nae.ip()))
341 QList<QHostAddress> blist;
353 QReadLocker rlock(&
naLock);
355 QList<QHostAddress> blist;
356 for (
const auto & nae : std::as_const(
naList_4))
358 if (!blist.contains(nae.broadcast()) && (nae.prefixLength() != 32) &&
359 (nae.ip() != QHostAddress::LocalHost))
360 blist << nae.broadcast();
368 QList<QHostAddress> blist;
369 blist << QHostAddress(
"FF02::1");
379 server->disconnect();
381 server->deleteLater();
387 socket->disconnect();
389 socket->deleteLater();
399 for (
const auto & qha : std::as_const(addrs))
403 if (qha.protocol() == QAbstractSocket::IPv4Protocol
408 if (qha.protocol() == QAbstractSocket::IPv6Protocol
419 if (server->listen(qha,
m_port))
421 LOG(VB_GENERAL, LOG_INFO, QString(
"Listening on TCP%1 %2:%3")
422 .arg(servertype ==
kSSLServer ?
" (SSL)" :
"",
423 prettyip(qha), QString::number(port)));
427 m_port = server->serverPort();
431 LOG(VB_GENERAL, LOG_ERR,
432 QString(
"Failed listening on TCP %1:%2 - Error %3: %4")
435 .arg(server->serverError())
436 .arg(server->errorString()));
437 server->disconnect();
438 server->deleteLater();
440 if (server->serverError() == QAbstractSocket::HostNotFoundError ||
441 server->serverError() == QAbstractSocket::SocketAddressNotAvailableError)
443 LOG(VB_GENERAL, LOG_ERR,
444 QString(
"Address %1 no longer exists - ignoring")
449 if (server->serverError() == QAbstractSocket::UnsupportedSocketOperationError
450 && qha.protocol() == QAbstractSocket::IPv4Protocol)
452 LOG(VB_GENERAL, LOG_INFO,
453 QString(
"IPv4 support failed for this port."));
457 if (server->serverError() == QAbstractSocket::UnsupportedSocketOperationError
458 && qha.protocol() == QAbstractSocket::IPv6Protocol)
460 LOG(VB_GENERAL, LOG_INFO,
461 QString(
"IPv6 support failed for this port."));
483 QList<QHostAddress> addrs;
484 for (
const auto & str : std::as_const(addrstr))
485 addrs << QHostAddress(str);
486 return listen(addrs, port, requireall, servertype);
499 for (
const auto & qha : std::as_const(addrs))
503 if (qha.protocol() == QAbstractSocket::IPv4Protocol
508 if (qha.protocol() == QAbstractSocket::IPv6Protocol
512 QNetworkAddressEntry host;
513 QNetworkAddressEntry wildcard;
515 if (qha.protocol() == QAbstractSocket::IPv6Protocol)
517 for (
const auto& iae : std::as_const(
naList_6))
524 if (iae.ip() == QHostAddress::AnyIPv6)
530 for (
const auto& iae : std::as_const(
naList_4))
537 if (iae.ip() == QHostAddress::AnyIPv4)
542 if (host.ip().isNull())
544 if (wildcard.ip().isNull())
546 LOG(VB_GENERAL, LOG_ERR,
547 QString(
"Failed to find local address to use for destination %1:%2.")
552 LOG(VB_GENERAL, LOG_DEBUG,
553 QString(
"Failed to find local address to use for destination %1:%2. Using wildcard.")
560 if (socket->bind(qha, port))
562 LOG(VB_GENERAL, LOG_INFO, QString(
"Binding to UDP %1:%2")
565 connect(socket, &QIODevice::readyRead,
570 LOG(VB_GENERAL, LOG_ERR,
571 QString(
"Failed binding to UDP %1:%2 - Error %3: %4")
574 .arg(socket->error())
575 .arg(socket->errorString()));
576 socket->disconnect();
577 socket->deleteLater();
579 if (socket->error() == QAbstractSocket::SocketAddressNotAvailableError)
581 LOG(VB_GENERAL, LOG_ERR,
582 QString(
"Address %1 no longer exists - ignoring")
604 QList<QHostAddress> addrs;
605 for (
const auto & str : std::as_const(addrstr))
606 addrs << QHostAddress(str);
607 return bind(addrs, port, requireall);
616 const QHostAddress &addr, quint16 port)
620 LOG(VB_GENERAL, LOG_ERR,
"Trying to write datagram to disconnected "
621 "ServerPool instance.");
629 QList<PrivUdpSocket*>::iterator it;
643 LOG(VB_GENERAL, LOG_DEBUG,
644 QString(
"No exact socket match for %1:%2. Searching for wildcard.")
648 if ((addr.protocol() == QAbstractSocket::IPv6Protocol &&
649 val->host().ip() == QHostAddress::AnyIPv6) ||
650 (val->host().ip() == QHostAddress::AnyIPv4))
659 LOG(VB_GENERAL, LOG_DEBUG, QString(
"No m_lastUdpSocket"));
666 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Error = %1 : %2")
673 const QHostAddress &addr, quint16 port)
675 return writeDatagram(datagram.data(), datagram.size(), addr, port);
682 auto *server = qobject_cast<PrivTcpServer *>(QObject::sender());
683 if (!server || server->GetServerType() ==
kSSLServer)
686 auto *qsock =
new QTcpSocket(
this);
687 if (qsock->setSocketDescriptor(socket)
700 auto *socket = qobject_cast<QUdpSocket*>(sender());
702 while (socket->state() == QAbstractSocket::BoundState &&
703 socket->hasPendingDatagrams())
706 buffer.resize(socket->pendingDatagramSize());
708 quint16 senderPort = 0;
710 socket->readDatagram(buffer.data(), buffer.size(),
711 &sender, &senderPort);
734 while (port < baseport + range)
743 if (port >= baseport + range)
767 while (port < baseport + range)
776 if (port >= baseport + range)
800 int range,
bool *isipv6)
805 while (port < baseport + range)
809 if (server->listen(QHostAddress::AnyIPv6, port))
815 QAbstractSocket::SocketError err = server->serverError();
816 if (err == QAbstractSocket::UnsupportedSocketOperationError)
823 if (server->listen(QHostAddress::Any, port))
836 if (port >= baseport + range)
842 port = server->serverPort();
864 int range,
bool *isipv6)
869 while (port < baseport + range)
873 if (socket->bind(QHostAddress::AnyIPv6, port))
879 QAbstractSocket::SocketError err = socket->error();
880 if (err == QAbstractSocket::UnsupportedSocketOperationError)
887 if (socket->bind(QHostAddress::Any, port))
900 if (port >= baseport + range)