MythTV  master
serverpool.cpp
Go to the documentation of this file.
1 #include <QNetworkAddressEntry>
2 #include <QReadWriteLock>
3 #include <QWriteLocker>
4 #include <QReadLocker>
5 #include <QTcpSocket>
6 
7 #include "mythcorecontext.h"
8 #include "mythlogging.h"
9 #include "serverpool.h"
10 
11 #define PRETTYIP(x) ((x)->protocol() == QAbstractSocket::IPv6Protocol ? \
12  "[" + (x)->toString().toLower() + "]" : \
13  (x)->toString().toLower())
14 #define PRETTYIP_(x) ((x).protocol() == QAbstractSocket::IPv6Protocol ? \
15  "[" + (x).toString().toLower() + "]" : \
16  (x).toString().toLower())
17 
18 #define LOC QString("ServerPool: ")
19 
20 static QList<QNetworkAddressEntry> naList_4;
21 static QList<QNetworkAddressEntry> naList_6;
22 static QReadWriteLock naLock;
23 
24 static QPair<QHostAddress, int> kLinkLocal =
25  QHostAddress::parseSubnet("169.254.0.0/16");
26 static QPair<QHostAddress, int> kLinkLocal6 =
27  QHostAddress::parseSubnet("fe80::/10");
28 
29 class PrivUdpSocket : public QUdpSocket
30 {
31 public:
32  PrivUdpSocket(QObject *parent, const QNetworkAddressEntry& host) :
33  QUdpSocket(parent), m_host(host) { };
34  ~PrivUdpSocket() override = default;
35  QNetworkAddressEntry host()
36  {
37  return m_host;
38  };
39  bool contains(const QHostAddress& addr)
40  {
41  return contains(m_host, addr);
42  };
43  static bool contains(const QNetworkAddressEntry& host, const QHostAddress& addr)
44  {
45  if (addr.protocol() == QAbstractSocket::IPv6Protocol &&
46  addr.isInSubnet(kLinkLocal6) &&
47  host.ip().scopeId() != addr.scopeId())
48  {
49  return false;
50  }
51  return addr.isInSubnet(host.ip(), host.prefixLength());
52  }
53 private:
54  QNetworkAddressEntry m_host;
55 };
56 
58  : QTcpServer(parent), m_serverType(type)
59 {
60 }
61 
63 {
64  emit newConnection(socket);
65 }
66 
68 {
69  close();
70 }
71 
73 {
74  if (!force)
75  {
76  QReadLocker rlock(&naLock);
77  if (!naList_4.isEmpty() || !naList_6.isEmpty())
78  // lists are already populated, do nothing
79  return;
80  }
81 
82  QWriteLocker wlock(&naLock);
83  naList_4.clear();
84  naList_6.clear();
85 
86  if (gCoreContext->GetBoolSetting("ListenOnAllIps",true))
87  {
88  QNetworkAddressEntry entry;
89  entry.setIp(QHostAddress(QHostAddress::AnyIPv4));
90  naList_4.append(entry);
91  entry.setIp(QHostAddress(QHostAddress::AnyIPv6));
92  naList_6.append(entry);
93  return;
94  }
95 
96  // populate stored IPv4 and IPv6 addresses
97  QHostAddress config_v4(gCoreContext->resolveSettingAddress(
98  "BackendServerIP",
99  QString(),
100  gCoreContext->ResolveIPv4, true));
101  bool v4IsSet = config_v4.isNull();
102  QHostAddress config_v6(gCoreContext->resolveSettingAddress(
103  "BackendServerIP6",
104  QString(),
105  gCoreContext->ResolveIPv6, true));
106  bool v6IsSet = config_v6.isNull();
107  bool allowLinkLocal = gCoreContext->GetBoolSetting("AllowLinkLocal", true);
108 
109  // loop through all available interfaces
110  QList<QNetworkInterface> IFs = QNetworkInterface::allInterfaces();
111  for (const auto & qni : qAsConst(IFs))
112  {
113  if ((qni.flags() & QNetworkInterface::IsRunning) == 0)
114  continue;
115 
116  QList<QNetworkAddressEntry> IPs = qni.addressEntries();
117  // C+11 range-for should only be used on const Qt lists, and
118  // this next loop modifies the list items.
119  // NOLINTNEXTLINE(modernize-loop-convert)
120  for (auto qnai = IPs.begin(); qnai != IPs.end(); ++qnai)
121  {
122  QHostAddress ip = qnai->ip();
123  if (ip.protocol() == QAbstractSocket::IPv4Protocol)
124  {
125  if (naList_4.contains(*qnai))
126  // already defined, skip
127  continue;
128 
129  if (!config_v4.isNull() && (ip == config_v4))
130  {
131  // IPv4 address is defined, add it
132  LOG(VB_GENERAL, LOG_DEBUG,
133  QString("Adding BackendServerIP to address list."));
134  naList_4.append(*qnai);
135  v4IsSet = true;
136 
137  }
138 
139  else if (ip == QHostAddress::LocalHost)
140  {
141  // always listen on LocalHost
142  LOG(VB_GENERAL, LOG_DEBUG,
143  QString("Adding IPv4 loopback to address list."));
144  naList_4.append(*qnai);
145  if (!v4IsSet && (config_v4 == ip))
146  v4IsSet = true;
147  }
148 
149  else if (ip.isInSubnet(kLinkLocal) && allowLinkLocal)
150  {
151  // optionally listen on linklocal
152  // the next clause will enable it anyway if no IP address
153  // has been set
154  LOG(VB_GENERAL, LOG_DEBUG,
155  QString("Adding link-local '%1' to address list.")
156  .arg(PRETTYIP_(ip)));
157  naList_4.append(*qnai);
158  }
159 
160  else if (config_v4.isNull())
161  {
162  // IPv4 address is not defined, populate one
163  // restrict autoconfiguration to RFC1918 private networks
164  static QPair<QHostAddress, int>
165  s_privNet1 = QHostAddress::parseSubnet("10.0.0.0/8");
166  static QPair<QHostAddress, int>
167  s_privNet2 = QHostAddress::parseSubnet("172.16.0.0/12");
168  static QPair<QHostAddress, int>
169  s_privNet3 = QHostAddress::parseSubnet("192.168.0.0/16");
170 
171  if (ip.isInSubnet(s_privNet1) || ip.isInSubnet(s_privNet2) ||
172  ip.isInSubnet(s_privNet3))
173  {
174  LOG(VB_GENERAL, LOG_DEBUG,
175  QString("Adding '%1' to address list.")
176  .arg(PRETTYIP_(ip)));
177  naList_4.append(*qnai);
178  }
179  else if (ip.isInSubnet(kLinkLocal))
180  {
181  LOG(VB_GENERAL, LOG_DEBUG,
182  QString("Adding link-local '%1' to address list.")
183  .arg(PRETTYIP_(ip)));
184  naList_4.append(*qnai);
185  }
186  else
187  {
188  LOG(VB_GENERAL, LOG_DEBUG, QString("Skipping "
189  "non-private address during IPv4 autoselection: %1")
190  .arg(PRETTYIP_(ip)));
191  }
192  }
193 
194  else
195  LOG(VB_GENERAL, LOG_DEBUG, QString("Skipping address: %1")
196  .arg(PRETTYIP_(ip)));
197 
198  }
199  else
200  {
201  if (ip.isInSubnet(kLinkLocal6))
202  {
203  // set scope id for link local address
204  ip.setScopeId(qni.name());
205  qnai->setIp(ip);
206  }
207 
208  if (naList_6.contains(*qnai))
209  // already defined, skip
210  continue;
211 
212  if ((!config_v6.isNull()) && (ip == config_v6))
213  {
214  // IPv6 address is defined, add it
215  LOG(VB_GENERAL, LOG_DEBUG,
216  QString("Adding BackendServerIP6 to address list."));
217  naList_6.append(*qnai);
218  v6IsSet = true;
219  }
220 
221  else if (ip == QHostAddress::LocalHostIPv6)
222  {
223  // always listen on LocalHost
224  LOG(VB_GENERAL, LOG_DEBUG,
225  QString("Adding IPv6 loopback to address list."));
226  naList_6.append(*qnai);
227  if (!v6IsSet && (config_v6 == ip))
228  v6IsSet = true;
229  }
230 
231  else if (ip.isInSubnet(kLinkLocal6) && allowLinkLocal)
232  {
233  // optionally listen on linklocal
234  // the next clause will enable it anyway if no IP address
235  // has been set
236  LOG(VB_GENERAL, LOG_DEBUG,
237  QString("Adding link-local '%1' to address list.")
238  .arg(ip.toString()));
239  naList_6.append(*qnai);
240  }
241 
242  else if (config_v6.isNull())
243  {
244  if (ip.isInSubnet(kLinkLocal6))
245  {
246  LOG(VB_GENERAL, LOG_DEBUG,
247  QString("Adding link-local '%1' to address list.")
248  .arg(PRETTYIP_(ip)));
249  }
250  else
251  {
252  LOG(VB_GENERAL, LOG_DEBUG,
253  QString("Adding '%1' to address list.")
254  .arg(PRETTYIP_(ip)));
255  }
256 
257  naList_6.append(*qnai);
258  }
259 
260  else
261  LOG(VB_GENERAL, LOG_DEBUG, QString("Skipping address: %1")
262  .arg(PRETTYIP_(ip)));
263  }
264  }
265  }
266 
267  if (!v4IsSet && (config_v4 != QHostAddress::LocalHost)
268  && !naList_4.isEmpty())
269  {
270  LOG(VB_GENERAL, LOG_CRIT, LOC + QString("Host is configured to listen "
271  "on %1, but address is not used on any local network "
272  "interfaces.").arg(config_v4.toString()));
273  }
274 
275  if (!v6IsSet && (config_v6 != QHostAddress::LocalHostIPv6)
276  && !naList_6.isEmpty())
277  {
278  LOG(VB_GENERAL, LOG_CRIT, LOC + QString("Host is configured to listen "
279  "on %1, but address is not used on any local network "
280  "interfaces.").arg(PRETTYIP_(config_v6)));
281  }
282 
283  // NOTE: there is no warning for the case where both defined addresses
284  // are localhost, and neither are found. however this would also
285  // mean there is no configured network at all, and should be
286  // sufficiently rare a case as to not worry about it.
287 }
288 
290 {
291  SelectDefaultListen(true);
292  // TODO:
293  // send signal for any running servers to cycle their addresses
294  // will allow address configuration to be modified without a server
295  // reset for use with the migration to the mythtv-setup replacement
296 }
297 
298 QList<QHostAddress> ServerPool::DefaultListen(void)
299 {
300  QList<QHostAddress> alist;
301  alist << DefaultListenIPv4()
302  << DefaultListenIPv6();
303  return alist;
304 }
305 
306 QList<QHostAddress> ServerPool::DefaultListenIPv4(void)
307 {
309  QReadLocker rlock(&naLock);
310 
311  QList<QHostAddress> alist;
312  for (const auto & nae : qAsConst(naList_4))
313  if (!alist.contains(nae.ip()))
314  alist << nae.ip();
315 
316  return alist;
317 }
318 
319 QList<QHostAddress> ServerPool::DefaultListenIPv6(void)
320 {
322  QReadLocker rlock(&naLock);
323 
324  QList<QHostAddress> alist;
325  for (const auto & nae : qAsConst(naList_6))
326  if (!alist.contains(nae.ip()))
327  alist << nae.ip();
328 
329  return alist;
330 }
331 
332 QList<QHostAddress> ServerPool::DefaultBroadcast(void)
333 {
334  QList<QHostAddress> blist;
335  if (!gCoreContext->GetBoolSetting("ListenOnAllIps",true))
336  {
337  blist << DefaultBroadcastIPv4();
338  blist << DefaultBroadcastIPv6();
339  }
340  return blist;
341 }
342 
343 QList<QHostAddress> ServerPool::DefaultBroadcastIPv4(void)
344 {
346  QReadLocker rlock(&naLock);
347 
348  QList<QHostAddress> blist;
349  for (const auto & nae : qAsConst(naList_4))
350  {
351  if (!blist.contains(nae.broadcast()) && (nae.prefixLength() != 32) &&
352  (nae.ip() != QHostAddress::LocalHost))
353  blist << nae.broadcast();
354  }
355 
356  return blist;
357 }
358 
359 QList<QHostAddress> ServerPool::DefaultBroadcastIPv6(void)
360 {
361  QList<QHostAddress> blist;
362  blist << QHostAddress("FF02::1");
363  return blist;
364 }
365 
366 
368 {
369  while (!m_tcpServers.isEmpty())
370  {
371  PrivTcpServer *server = m_tcpServers.takeLast();
372  server->disconnect();
373  server->close();
374  server->deleteLater();
375  }
376 
377  while (!m_udpSockets.isEmpty())
378  {
379  PrivUdpSocket *socket = m_udpSockets.takeLast();
380  socket->disconnect();
381  socket->close();
382  socket->deleteLater();
383  }
384  m_lastUdpSocket = nullptr;
385  m_listening = false;
386 }
387 
388 bool ServerPool::listen(QList<QHostAddress> addrs, quint16 port,
389  bool requireall, PoolServerType servertype)
390 {
391  m_port = port;
392  for (const auto & qha : qAsConst(addrs))
393  {
394  // If IPV4 support is disabled and this is an IPV4 address,
395  // bypass this address
396  if (qha.protocol() == QAbstractSocket::IPv4Protocol
397  && ! gCoreContext->GetBoolSetting("IPv4Support",true))
398  continue;
399  // If IPV6 support is disabled and this is an IPV6 address,
400  // bypass this address
401  if (qha.protocol() == QAbstractSocket::IPv6Protocol
402  && ! gCoreContext->GetBoolSetting("IPv6Support",true))
403  continue;
404 
405  auto *server = new PrivTcpServer(this, servertype);
406  connect(server, &PrivTcpServer::newConnection,
408 
409  server->setProxy(m_proxy);
410  server->setMaxPendingConnections(m_maxPendingConn);
411 
412  if (server->listen(qha, m_port))
413  {
414  LOG(VB_GENERAL, LOG_INFO, QString("Listening on TCP %1:%2")
415  .arg(PRETTYIP_(qha)).arg(port));
416  if (servertype == kTCPServer)
417  m_tcpServers.append(server);
418  if (m_port == 0)
419  m_port = server->serverPort();
420  }
421  else
422  {
423  LOG(VB_GENERAL, LOG_ERR,
424  QString("Failed listening on TCP %1:%2 - Error %3: %4")
425  .arg(PRETTYIP_(qha))
426  .arg(port)
427  .arg(server->serverError())
428  .arg(server->errorString()));
429  server->disconnect();
430  server->deleteLater();
431 
432  if (server->serverError() == QAbstractSocket::HostNotFoundError ||
433  server->serverError() == QAbstractSocket::SocketAddressNotAvailableError)
434  {
435  LOG(VB_GENERAL, LOG_ERR,
436  QString("Address %1 no longer exists - ignoring")
437  .arg(PRETTYIP_(qha)));
438  continue;
439  }
440 
441  if (server->serverError() == QAbstractSocket::UnsupportedSocketOperationError
442  && qha.protocol() == QAbstractSocket::IPv4Protocol)
443  {
444  LOG(VB_GENERAL, LOG_INFO,
445  QString("IPv4 support failed for this port."));
446  continue;
447  }
448 
449  if (server->serverError() == QAbstractSocket::UnsupportedSocketOperationError
450  && qha.protocol() == QAbstractSocket::IPv6Protocol)
451  {
452  LOG(VB_GENERAL, LOG_INFO,
453  QString("IPv6 support failed for this port."));
454  continue;
455  }
456 
457  if (requireall)
458  {
459  close();
460  return false;
461  }
462  }
463  }
464 
465  if (m_tcpServers.empty())
466  return false;
467 
468  m_listening = true;
469  return true;
470 }
471 
472 bool ServerPool::listen(QStringList addrstr, quint16 port, bool requireall,
473  PoolServerType servertype)
474 {
475  QList<QHostAddress> addrs;
476  for (const auto & str : qAsConst(addrstr))
477  addrs << QHostAddress(str);
478  return listen(addrs, port, requireall, servertype);
479 }
480 
481 bool ServerPool::listen(quint16 port, bool requireall,
482  PoolServerType servertype)
483 {
484  return listen(DefaultListen(), port, requireall, servertype);
485 }
486 
487 bool ServerPool::bind(QList<QHostAddress> addrs, quint16 port,
488  bool requireall)
489 {
490  m_port = port;
491  for (const auto & qha : qAsConst(addrs))
492  {
493  // If IPV4 support is disabled and this is an IPV4 address,
494  // bypass this address
495  if (qha.protocol() == QAbstractSocket::IPv4Protocol
496  && ! gCoreContext->GetBoolSetting("IPv4Support",true))
497  continue;
498  // If IPV6 support is disabled and this is an IPV6 address,
499  // bypass this address
500  if (qha.protocol() == QAbstractSocket::IPv6Protocol
501  && ! gCoreContext->GetBoolSetting("IPv6Support",true))
502  continue;
503 
504  QNetworkAddressEntry host;
505 
506  auto sameaddr = [qha](const auto & iae)
507  {return PrivUdpSocket::contains(iae, qha); };
508  if (qha.protocol() == QAbstractSocket::IPv6Protocol)
509  {
510  auto it = std::find_if(naList_6.cbegin(), naList_6.cend(), sameaddr);
511  if (it != naList_6.cend())
512  host = *it;
513  }
514  else
515  {
516  auto it = std::find_if(naList_4.cbegin(), naList_4.cend(), sameaddr);
517  if (it != naList_4.cend())
518  host = *it;
519  }
520 
521  auto *socket = new PrivUdpSocket(this, host);
522 
523  if (socket->bind(qha, port))
524  {
525  LOG(VB_GENERAL, LOG_INFO, QString("Binding to UDP %1:%2")
526  .arg(PRETTYIP_(qha)).arg(port));
527  m_udpSockets.append(socket);
528  connect(socket, &QIODevice::readyRead,
530  }
531  else
532  {
533  LOG(VB_GENERAL, LOG_ERR,
534  QString("Failed binding to UDP %1:%2 - Error %3: %4")
535  .arg(PRETTYIP_(qha))
536  .arg(port)
537  .arg(socket->error())
538  .arg(socket->errorString()));
539  socket->disconnect();
540  socket->deleteLater();
541 
542  if (socket->error() == QAbstractSocket::SocketAddressNotAvailableError)
543  {
544  LOG(VB_GENERAL, LOG_ERR,
545  QString("Address %1 no longer exists - ignoring")
546  .arg(PRETTYIP_(qha)));
547  continue;
548  }
549 
550  if (requireall)
551  {
552  close();
553  return false;
554  }
555  }
556  }
557 
558  if (m_udpSockets.empty())
559  return false;
560 
561  m_listening = true;
562  return true;
563 }
564 
565 bool ServerPool::bind(QStringList addrstr, quint16 port, bool requireall)
566 {
567  QList<QHostAddress> addrs;
568  for (const auto & str : qAsConst(addrstr))
569  addrs << QHostAddress(str);
570  return bind(addrs, port, requireall);
571 }
572 
573 bool ServerPool::bind(quint16 port, bool requireall)
574 {
575  // cppcheck-suppress invalidFunctionArgBool
576  return bind(DefaultListen(), port, requireall);
577 }
578 
579 qint64 ServerPool::writeDatagram(const char * data, qint64 size,
580  const QHostAddress &addr, quint16 port)
581 {
582  if (!m_listening || m_udpSockets.empty())
583  {
584  LOG(VB_GENERAL, LOG_ERR, "Trying to write datagram to disconnected "
585  "ServerPool instance.");
586  return -1;
587  }
588 
589  // check if can re-use the last one, so there's no need for a linear search
590  if (!m_lastUdpSocket || !m_lastUdpSocket->contains(addr))
591  {
592  // find the right socket to use
593  QList<PrivUdpSocket*>::iterator it;
594  for (it = m_udpSockets.begin(); it != m_udpSockets.end(); ++it)
595  {
596  PrivUdpSocket *val = *it;
597  if (val->contains(addr))
598  {
599  m_lastUdpSocket = val;
600  break;
601  }
602  }
603  }
604  if (!m_lastUdpSocket)
605  return -1;
606 
607  qint64 ret = m_lastUdpSocket->writeDatagram(data, size, addr, port);
608  if (ret != size)
609  {
610  LOG(VB_GENERAL, LOG_DEBUG, QString("Error = %1 : %2")
611  .arg(ret).arg(m_lastUdpSocket->error()));
612  }
613  return ret;
614 }
615 
616 qint64 ServerPool::writeDatagram(const QByteArray &datagram,
617  const QHostAddress &addr, quint16 port)
618 {
619  return writeDatagram(datagram.data(), datagram.size(), addr, port);
620 }
621 
623 {
624  // Ignore connections from an SSL server for now, these are only handled
625  // by HttpServer which overrides newTcpConnection
626  auto *server = qobject_cast<PrivTcpServer *>(QObject::sender());
627  if (!server || server->GetServerType() == kSSLServer)
628  return;
629 
630  auto *qsock = new QTcpSocket(this);
631  if (qsock->setSocketDescriptor(socket)
632  && gCoreContext->CheckSubnet(qsock))
633  {
634  emit newConnection(qsock);
635  }
636  else
637  delete qsock;
638 }
639 
641 {
642  auto *socket = qobject_cast<QUdpSocket*>(sender());
643 
644  while (socket->state() == QAbstractSocket::BoundState &&
645  socket->hasPendingDatagrams())
646  {
647  QByteArray buffer;
648  buffer.resize(socket->pendingDatagramSize());
649  QHostAddress sender;
650  quint16 senderPort = 0;
651 
652  socket->readDatagram(buffer.data(), buffer.size(),
653  &sender, &senderPort);
654  if (gCoreContext->CheckSubnet(sender))
655  emit newDatagram(buffer, sender, senderPort);
656  }
657 }
658 
672 int ServerPool::tryListeningPort(int baseport, int range)
673 {
674  // try a few ports in case the first is in use
675  int port = baseport;
676  while (port < baseport + range)
677  {
678  if (listen(port))
679  {
680  break;
681  }
682  port++;
683  }
684 
685  if (port >= baseport + range)
686  {
687  return -1;
688  }
689  return port;
690 }
691 
705 int ServerPool::tryBindingPort(int baseport, int range)
706 {
707  // try a few ports in case the first is in use
708  int port = baseport;
709  while (port < baseport + range)
710  {
711  if (bind(port))
712  {
713  break;
714  }
715  port++;
716  }
717 
718  if (port >= baseport + range)
719  {
720  return -1;
721  }
722  return port;
723 }
724 
741 int ServerPool::tryListeningPort(QTcpServer *server, int baseport,
742  int range, bool *isipv6)
743 {
744  bool ipv6 = true;
745  // try a few ports in case the first is in use
746  int port = baseport;
747  while (port < baseport + range)
748  {
749  if (ipv6)
750  {
751  if (server->listen(QHostAddress::AnyIPv6, port))
752  {
753  break;
754  }
755 
756  // did we fail because IPv6 isn't available?
757  QAbstractSocket::SocketError err = server->serverError();
758  if (err == QAbstractSocket::UnsupportedSocketOperationError)
759  {
760  ipv6 = false;
761  }
762  }
763  if (!ipv6)
764  {
765  if (server->listen(QHostAddress::Any, port))
766  {
767  break;
768  }
769  }
770  port++;
771  }
772 
773  if (isipv6)
774  {
775  *isipv6 = ipv6;
776  }
777 
778  if (port >= baseport + range)
779  {
780  return -1;
781  }
782  if (port == 0)
783  {
784  port = server->serverPort();
785  }
786  return port;
787 }
788 
805 int ServerPool::tryBindingPort(QUdpSocket *socket, int baseport,
806  int range, bool *isipv6)
807 {
808  bool ipv6 = true;
809  // try a few ports in case the first is in use
810  int port = baseport;
811  while (port < baseport + range)
812  {
813  if (ipv6)
814  {
815  if (socket->bind(QHostAddress::AnyIPv6, port))
816  {
817  break;
818  }
819 
820  // did we fail because IPv6 isn't available?
821  QAbstractSocket::SocketError err = socket->error();
822  if (err == QAbstractSocket::UnsupportedSocketOperationError)
823  {
824  ipv6 = false;
825  }
826  }
827  if (!ipv6)
828  {
829  if (socket->bind(QHostAddress::Any, port))
830  {
831  break;
832  }
833  }
834  port++;
835  }
836 
837  if (isipv6)
838  {
839  *isipv6 = ipv6;
840  }
841 
842  if (port >= baseport + range)
843  {
844  return -1;
845  }
846  return port;
847 }
naList_4
static QList< QNetworkAddressEntry > naList_4
Definition: serverpool.cpp:20
force
bool force
Definition: mythtv/programs/mythcommflag/main.cpp:74
MythCoreContext::resolveSettingAddress
QString resolveSettingAddress(const QString &name, const QString &host=QString(), ResolveType type=ResolveAny, bool keepscope=false)
Retrieve IP setting "name" for "host".
Definition: mythcorecontext.cpp:1168
PrivUdpSocket::contains
bool contains(const QHostAddress &addr)
Definition: serverpool.cpp:39
kSSLServer
@ kSSLServer
Definition: serverpool.h:33
ServerPool::~ServerPool
~ServerPool(void) override
Definition: serverpool.cpp:67
kLinkLocal6
static QPair< QHostAddress, int > kLinkLocal6
Definition: serverpool.cpp:26
ServerPool::newDatagram
void newDatagram(QByteArray, QHostAddress, quint16)
ServerPool::close
void close(void)
Definition: serverpool.cpp:367
naList_6
static QList< QNetworkAddressEntry > naList_6
Definition: serverpool.cpp:21
PrivUdpSocket::PrivUdpSocket
PrivUdpSocket(QObject *parent, const QNetworkAddressEntry &host)
Definition: serverpool.cpp:32
ServerPool::m_lastUdpSocket
PrivUdpSocket * m_lastUdpSocket
Definition: serverpool.h:128
PrivUdpSocket
Definition: serverpool.cpp:30
PrivTcpServer::newConnection
void newConnection(qt_socket_fd_t socket)
ServerPool::tryBindingPort
int tryBindingPort(int baseport, int range=1)
tryBindingPort
Definition: serverpool.cpp:705
PrivTcpServer::PrivTcpServer
PrivTcpServer(QObject *parent=nullptr, PoolServerType type=kTCPServer)
Definition: serverpool.cpp:57
ServerPool::DefaultListenIPv4
static QList< QHostAddress > DefaultListenIPv4(void)
Definition: serverpool.cpp:306
arg
arg(title).arg(filename).arg(doDelete))
ServerPool::tryListeningPort
int tryListeningPort(int baseport, int range=1)
tryListeningPort
Definition: serverpool.cpp:672
ServerPool::m_udpSockets
QList< PrivUdpSocket * > m_udpSockets
Definition: serverpool.h:127
ServerPool::DefaultBroadcastIPv6
static QList< QHostAddress > DefaultBroadcastIPv6(void)
Definition: serverpool.cpp:359
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
ServerPool::DefaultBroadcastIPv4
static QList< QHostAddress > DefaultBroadcastIPv4(void)
Definition: serverpool.cpp:343
ServerPool::newConnection
void newConnection(QTcpSocket *)
PrivUdpSocket::~PrivUdpSocket
~PrivUdpSocket() override=default
PrivTcpServer::incomingConnection
void incomingConnection(qt_socket_fd_t socket) override
Definition: serverpool.cpp:62
ServerPool::writeDatagram
qint64 writeDatagram(const char *data, qint64 size, const QHostAddress &addr, quint16 port)
Definition: serverpool.cpp:579
ServerPool::m_proxy
QNetworkProxy m_proxy
Definition: serverpool.h:124
mythlogging.h
ServerPool::newUdpDatagram
virtual void newUdpDatagram(void)
Definition: serverpool.cpp:640
PrivUdpSocket::contains
static bool contains(const QNetworkAddressEntry &host, const QHostAddress &addr)
Definition: serverpool.cpp:43
PrivTcpServer
Definition: serverpool.h:40
ServerPool::newTcpConnection
virtual void newTcpConnection(qt_socket_fd_t socket)
Definition: serverpool.cpp:622
PoolServerType
PoolServerType
Definition: serverpool.h:30
PrivUdpSocket::host
QNetworkAddressEntry host()
Definition: serverpool.cpp:35
ServerPool::RefreshDefaultListen
static void RefreshDefaultListen(void)
Definition: serverpool.cpp:289
ServerPool::DefaultListen
static QList< QHostAddress > DefaultListen(void)
Definition: serverpool.cpp:298
ServerPool::m_maxPendingConn
int m_maxPendingConn
Definition: serverpool.h:122
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:56
ServerPool::bind
bool bind(QList< QHostAddress > addrs, quint16 port, bool requireall=true)
Definition: serverpool.cpp:487
ServerPool::SelectDefaultListen
static void SelectDefaultListen(bool force=false)
Definition: serverpool.cpp:72
MythCoreContext::ResolveIPv6
@ ResolveIPv6
Definition: mythcorecontext.h:193
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:923
ServerPool::m_tcpServers
QList< PrivTcpServer * > m_tcpServers
Definition: serverpool.h:126
MythCoreContext::ResolveIPv4
@ ResolveIPv4
Definition: mythcorecontext.h:193
mythcorecontext.h
naLock
static QReadWriteLock naLock
Definition: serverpool.cpp:22
LOC
#define LOC
Definition: serverpool.cpp:18
kLinkLocal
static QPair< QHostAddress, int > kLinkLocal
Definition: serverpool.cpp:24
serverpool.h
PRETTYIP_
#define PRETTYIP_(x)
Definition: serverpool.cpp:14
ServerPool::m_port
quint16 m_port
Definition: serverpool.h:123
ServerPool::m_listening
bool m_listening
Definition: serverpool.h:121
ServerPool::listen
bool listen(QList< QHostAddress > addrs, quint16 port, bool requireall=true, PoolServerType type=kTCPServer)
Definition: serverpool.cpp:388
ServerPool::DefaultBroadcast
static QList< QHostAddress > DefaultBroadcast(void)
Definition: serverpool.cpp:332
ServerPool::DefaultListenIPv6
static QList< QHostAddress > DefaultListenIPv6(void)
Definition: serverpool.cpp:319
MythCoreContext::CheckSubnet
bool CheckSubnet(const QAbstractSocket *socket)
Check if a socket is connected to an approved peer.
Definition: mythcorecontext.cpp:1273
qt_socket_fd_t
qintptr qt_socket_fd_t
Definition: mythqtcompat.h:4
kTCPServer
@ kTCPServer
Definition: serverpool.h:31
PrivUdpSocket::m_host
QNetworkAddressEntry m_host
Definition: serverpool.cpp:54