Skip to content

Commit

Permalink
Always use the loopback interface when local
Browse files Browse the repository at this point in the history
If the backend is local to the frontend then we will always use the
loopback interface instead of connecting on the external IP. This adds
some resilience to setups where the network connection may drop, e.g.
using wifi - especially Ubuntu which removes the IP from the interface
if it detects that the network is unreachable.
  • Loading branch information
stuartm committed Aug 11, 2011
1 parent fcb124d commit 50606cd
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
37 changes: 36 additions & 1 deletion mythtv/libs/libmythbase/mythsocket.cpp
Expand Up @@ -13,6 +13,8 @@
// Qt
#include <QByteArray>
#include <QHostInfo>
#include <QNetworkInterface> // for QNetworkInterface::allAddresses ()
#include <QAbstractSocket> // for QAbstractSocket::NetworkLayerProtocol
#include <QMap>
#include <QCoreApplication>

Expand All @@ -37,6 +39,8 @@ const uint MythSocket::kLongTimeout = kMythSocketLongTimeout;
QMutex MythSocket::s_readyread_thread_lock;
MythSocketThread *MythSocket::s_readyread_thread = NULL;

QMap<QString, QHostAddress::SpecialAddress> MythSocket::s_loopback_cache;

MythSocket::MythSocket(int socket, MythSocketCBs *cb)
: MSocketDevice(MSocketDevice::Stream), m_cb(cb),
m_useReadyReadCallback(true),
Expand Down Expand Up @@ -752,6 +756,7 @@ void MythSocket::Unlock(bool wake_readyread) const
bool MythSocket::connect(const QString &host, quint16 port)
{
QHostAddress hadr;

if (!hadr.setAddress(host))
{
QHostInfo info = QHostInfo::fromName(host);
Expand All @@ -774,15 +779,45 @@ bool MythSocket::connect(const QString &host, quint16 port)
* \brief connect to host
* \return true on success
*/
bool MythSocket::connect(const QHostAddress &addr, quint16 port)
bool MythSocket::connect(const QHostAddress &hadr, quint16 port)
{
QHostAddress addr = hadr;

if (state() == Connected)
{
LOG(VB_SOCKET, LOG_ERR, LOC +
"connect() called with already open socket, closing");
close();
}

bool usingLoopback = false;
if (s_loopback_cache.contains(addr.toString()))
{
addr = QHostAddress(s_loopback_cache.value(addr.toString()));
usingLoopback = true;
}
else
{
QList<QHostAddress> localIPs = QNetworkInterface::allAddresses();
for (int i = 0; i < localIPs.count() && !usingLoopback; ++i)
{
if (addr == localIPs[i])
{
QHostAddress::SpecialAddress loopback = QHostAddress::LocalHost;
if (addr.protocol() == QAbstractSocket::IPv6Protocol)
loopback = QHostAddress::LocalHostIPv6;

s_loopback_cache[addr.toString()] = loopback;
addr = QHostAddress(loopback);
usingLoopback = true;
}
}
}

if (usingLoopback)
LOG(VB_SOCKET, LOG_INFO, LOC + QString("IP is local, using "
"loopback address instead"));

LOG(VB_SOCKET, LOG_INFO, LOC + QString("attempting connect() to (%1:%2)")
.arg(addr.toString()).arg(port));

Expand Down
7 changes: 6 additions & 1 deletion mythtv/libs/libmythbase/mythsocket.h
Expand Up @@ -9,6 +9,9 @@
#include "mythsocket_cb.h"
#include "mythbaseexp.h"

template<class T >
class QList;
class QString;
class QHostAddress;
class MythSocketThread;

Expand Down Expand Up @@ -73,7 +76,7 @@ class MBASE_PUBLIC MythSocket : public MSocketDevice
bool readData(char *data, quint64 len);
bool writeData(const char *data, quint64 len);

bool connect(const QHostAddress &addr, quint16 port);
bool connect(const QHostAddress &hadr, quint16 port);
bool connect(const QString &host, quint16 port);

void Lock(void) const;
Expand Down Expand Up @@ -107,6 +110,8 @@ class MBASE_PUBLIC MythSocket : public MSocketDevice
static const uint kSocketBufferSize;
static QMutex s_readyread_thread_lock;
static MythSocketThread *s_readyread_thread;

static QMap<QString, QHostAddress::SpecialAddress> s_loopback_cache;
};

#endif
Expand Down

0 comments on commit 50606cd

Please sign in to comment.