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 : qAsConst(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")
198 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Skipping address: %1")
207 ip.setScopeId(qni.name());
215 if ((!config_v6.isNull()) && (ip == config_v6))
218 LOG(VB_GENERAL, LOG_DEBUG,
219 QString(
"Adding BackendServerIP6 to address list."));
224 else if (ip == QHostAddress::LocalHostIPv6)
227 LOG(VB_GENERAL, LOG_DEBUG,
228 QString(
"Adding IPv6 loopback to address list."));
230 if (!v6IsSet && (config_v6 == ip))
234 else if (ip.isInSubnet(
kLinkLocal6) && allowLinkLocal)
239 LOG(VB_GENERAL, LOG_DEBUG,
240 QString(
"Adding link-local '%1' to address list.")
241 .arg(ip.toString()));
245 else if (config_v6.isNull())
249 LOG(VB_GENERAL, LOG_DEBUG,
250 QString(
"Adding link-local '%1' to address list.")
255 LOG(VB_GENERAL, LOG_DEBUG,
256 QString(
"Adding '%1' to address list.")
264 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Skipping address: %1")
270 if (!v4IsSet && (config_v4 != QHostAddress::LocalHost)
273 LOG(VB_GENERAL, LOG_CRIT,
LOC + QString(
"Host is configured to listen "
274 "on %1, but address is not used on any local network "
275 "interfaces.").arg(config_v4.toString()));
278 if (!v6IsSet && (config_v6 != QHostAddress::LocalHostIPv6)
281 LOG(VB_GENERAL, LOG_CRIT,
LOC + QString(
"Host is configured to listen "
282 "on %1, but address is not used on any local network "
283 "interfaces.").arg(
prettyip(config_v6)));
303 QList<QHostAddress> alist;
312 QReadLocker rlock(&
naLock);
314 QList<QHostAddress> alist;
315 for (
const auto & nae : qAsConst(
naList_4))
316 if (!alist.contains(nae.ip()))
325 QReadLocker rlock(&
naLock);
327 QList<QHostAddress> alist;
328 for (
const auto & nae : qAsConst(
naList_6))
329 if (!alist.contains(nae.ip()))
337 QList<QHostAddress> blist;
349 QReadLocker rlock(&
naLock);
351 QList<QHostAddress> blist;
352 for (
const auto & nae : qAsConst(
naList_4))
354 if (!blist.contains(nae.broadcast()) && (nae.prefixLength() != 32) &&
355 (nae.ip() != QHostAddress::LocalHost))
356 blist << nae.broadcast();
364 QList<QHostAddress> blist;
365 blist << QHostAddress(
"FF02::1");
375 server->disconnect();
377 server->deleteLater();
383 socket->disconnect();
385 socket->deleteLater();
395 for (
const auto & qha : qAsConst(addrs))
399 if (qha.protocol() == QAbstractSocket::IPv4Protocol
404 if (qha.protocol() == QAbstractSocket::IPv6Protocol
415 if (server->listen(qha,
m_port))
417 LOG(VB_GENERAL, LOG_INFO, QString(
"Listening on TCP%1 %2:%3")
418 .arg(servertype ==
kSSLServer ?
" (SSL)" :
"",
419 prettyip(qha), QString::number(port)));
423 m_port = server->serverPort();
427 LOG(VB_GENERAL, LOG_ERR,
428 QString(
"Failed listening on TCP %1:%2 - Error %3: %4")
431 .arg(server->serverError())
432 .arg(server->errorString()));
433 server->disconnect();
434 server->deleteLater();
436 if (server->serverError() == QAbstractSocket::HostNotFoundError ||
437 server->serverError() == QAbstractSocket::SocketAddressNotAvailableError)
439 LOG(VB_GENERAL, LOG_ERR,
440 QString(
"Address %1 no longer exists - ignoring")
445 if (server->serverError() == QAbstractSocket::UnsupportedSocketOperationError
446 && qha.protocol() == QAbstractSocket::IPv4Protocol)
448 LOG(VB_GENERAL, LOG_INFO,
449 QString(
"IPv4 support failed for this port."));
453 if (server->serverError() == QAbstractSocket::UnsupportedSocketOperationError
454 && qha.protocol() == QAbstractSocket::IPv6Protocol)
456 LOG(VB_GENERAL, LOG_INFO,
457 QString(
"IPv6 support failed for this port."));
479 QList<QHostAddress> addrs;
480 for (
const auto & str : qAsConst(addrstr))
481 addrs << QHostAddress(str);
482 return listen(addrs, port, requireall, servertype);
495 for (
const auto & qha : qAsConst(addrs))
499 if (qha.protocol() == QAbstractSocket::IPv4Protocol
504 if (qha.protocol() == QAbstractSocket::IPv6Protocol
508 QNetworkAddressEntry host;
509 QNetworkAddressEntry wildcard;
511 if (qha.protocol() == QAbstractSocket::IPv6Protocol)
513 for (
const auto& iae : qAsConst(
naList_6))
520 if (iae.ip() == QHostAddress::AnyIPv6)
526 for (
const auto& iae : qAsConst(
naList_4))
533 if (iae.ip() == QHostAddress::AnyIPv4)
538 if (host.ip().isNull())
540 if (wildcard.ip().isNull())
542 LOG(VB_GENERAL, LOG_ERR,
543 QString(
"Failed to find local address to use for destination %1:%2.")
548 LOG(VB_GENERAL, LOG_DEBUG,
549 QString(
"Failed to find local address to use for destination %1:%2. Using wildcard.")
556 if (socket->bind(qha, port))
558 LOG(VB_GENERAL, LOG_INFO, QString(
"Binding to UDP %1:%2")
561 connect(socket, &QIODevice::readyRead,
566 LOG(VB_GENERAL, LOG_ERR,
567 QString(
"Failed binding to UDP %1:%2 - Error %3: %4")
570 .arg(socket->error())
571 .arg(socket->errorString()));
572 socket->disconnect();
573 socket->deleteLater();
575 if (socket->error() == QAbstractSocket::SocketAddressNotAvailableError)
577 LOG(VB_GENERAL, LOG_ERR,
578 QString(
"Address %1 no longer exists - ignoring")
600 QList<QHostAddress> addrs;
601 for (
const auto & str : qAsConst(addrstr))
602 addrs << QHostAddress(str);
603 return bind(addrs, port, requireall);
612 const QHostAddress &addr, quint16 port)
616 LOG(VB_GENERAL, LOG_ERR,
"Trying to write datagram to disconnected "
617 "ServerPool instance.");
625 QList<PrivUdpSocket*>::iterator it;
639 LOG(VB_GENERAL, LOG_DEBUG,
640 QString(
"No exact socket match for %1:%2. Searching for wildcard.")
644 if ((addr.protocol() == QAbstractSocket::IPv6Protocol &&
645 val->host().ip() == QHostAddress::AnyIPv6) ||
646 (val->host().ip() == QHostAddress::AnyIPv4))
655 LOG(VB_GENERAL, LOG_DEBUG, QString(
"No m_lastUdpSocket"));
662 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Error = %1 : %2")
669 const QHostAddress &addr, quint16 port)
671 return writeDatagram(datagram.data(), datagram.size(), addr, port);
678 auto *server = qobject_cast<PrivTcpServer *>(QObject::sender());
679 if (!server || server->GetServerType() ==
kSSLServer)
682 auto *qsock =
new QTcpSocket(
this);
683 if (qsock->setSocketDescriptor(socket)
694 auto *socket = qobject_cast<QUdpSocket*>(sender());
696 while (socket->state() == QAbstractSocket::BoundState &&
697 socket->hasPendingDatagrams())
700 buffer.resize(socket->pendingDatagramSize());
702 quint16 senderPort = 0;
704 socket->readDatagram(buffer.data(), buffer.size(),
705 &sender, &senderPort);
728 while (port < baseport + range)
737 if (port >= baseport + range)
761 while (port < baseport + range)
770 if (port >= baseport + range)
794 int range,
bool *isipv6)
799 while (port < baseport + range)
803 if (server->listen(QHostAddress::AnyIPv6, port))
809 QAbstractSocket::SocketError err = server->serverError();
810 if (err == QAbstractSocket::UnsupportedSocketOperationError)
817 if (server->listen(QHostAddress::Any, port))
830 if (port >= baseport + range)
836 port = server->serverPort();
858 int range,
bool *isipv6)
863 while (port < baseport + range)
867 if (socket->bind(QHostAddress::AnyIPv6, port))
873 QAbstractSocket::SocketError err = socket->error();
874 if (err == QAbstractSocket::UnsupportedSocketOperationError)
881 if (socket->bind(QHostAddress::Any, port))
894 if (port >= baseport + range)