From fc7f4ab98efb64d6436882af8189af44715e3bb4 Mon Sep 17 00:00:00 2001 From: "craig.p.drummond@gmail.com" Date: Fri, 15 Jun 2012 11:40:53 +0000 Subject: [PATCH] Add option to specify HTTP server listen address/interface. --- ChangeLog | 1 + gui/httpserversettings.cpp | 2 ++ gui/httpserversettings.ui | 35 ++++++++++++++++++++---- gui/mainwindow.cpp | 6 +++- gui/settings.cpp | 10 +++++++ gui/settings.h | 2 ++ http/httpserver.cpp | 13 +++++---- http/httpserver.h | 2 +- http/httpsocket.cpp | 56 ++++++++++++++++++++++++++++++++++++-- http/httpsocket.h | 13 ++++++--- 10 files changed, 120 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3a423c1c1..1e786749c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -47,6 +47,7 @@ 29. Workaround tab-widget issues with Gtk style. Only draw highlight for selected item, and item curretly under mouse - no fade in/out. 30. Fix/workaround issues with fetching lyrics from letras.mus.br +31. Add option to specify HTTP server listen address/interface. 0.7.1 ----- diff --git a/gui/httpserversettings.cpp b/gui/httpserversettings.cpp index 67d665d9e..1496a5c5c 100644 --- a/gui/httpserversettings.cpp +++ b/gui/httpserversettings.cpp @@ -35,6 +35,7 @@ void HttpServerSettings::load() enableHttp->setChecked(Settings::self()->enableHttp()); alwaysUseHttp->setChecked(Settings::self()->alwaysUseHttp()); httpPort->setValue(Settings::self()->httpPort()); + httpAddress->setText(Settings::self()->httpAddress()); } void HttpServerSettings::save() @@ -42,4 +43,5 @@ void HttpServerSettings::save() Settings::self()->saveEnableHttp(enableHttp->isChecked()); Settings::self()->saveAlwaysUseHttp(alwaysUseHttp->isChecked()); Settings::self()->saveHttpPort(httpPort->value()); + Settings::self()->saveHttpAddress(httpAddress->text()); } diff --git a/gui/httpserversettings.ui b/gui/httpserversettings.ui index 9bd1aa81e..94788c5ae 100644 --- a/gui/httpserversettings.ui +++ b/gui/httpserversettings.ui @@ -6,8 +6,8 @@ 0 0 - 384 - 254 + 416 + 345 @@ -50,7 +50,7 @@ - + Port: @@ -60,7 +60,7 @@ - + 1 @@ -70,6 +70,19 @@ + + + + Address/interface: + + + httpAddress + + + + + + @@ -91,7 +104,8 @@ - <i><b>NOTE:</b> MPD usually only plays songs that are stored within its folders. If you have connected via a local socket, then MPD can also play files located on your filesystem. If you are using a non local socket (e.g. you have entered a hostname or IP address in the "Host" field of the "Server" settings page), then Cantata contains a minimal HTTP server that can be used to server files to MPD. This, however, will only work whilst Cantata is running. If you enable "Always use server", then Cantata will always pass server URLs to MPD for files, even when you have connected via a local socket.</i> + <b>NOTE:</b> MPD usually only plays songs that are stored within its folders. If you have connected via a local socket, then MPD can also play files located on your filesystem. If you are using a non local socket (e.g. you have entered a hostname or IP address in the "Host" field of the "Server" settings page), then Cantata contains a minimal HTTP server that can be used to server files to MPD. This, however, will only work whilst Cantata is running. If you enable "Always use server", then Cantata will always pass server URLs to MPD for files, even when you have connected via a local socket.<br/><br/> +<b>NOTE:</b>"Address/interface" may contian either the IP address, or interface (e.g. eth0), that you wish to listen for connections on. Leave blank to use the local loopback address (127.0.0.1).</i> true @@ -114,12 +128,23 @@ + + LineEdit + QLineEdit +
lineedit.h
+
BuddyLabel QLabel
buddylabel.h
+ + enableHttp + alwaysUseHttp + httpAddress + httpPort + diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index bcd318da4..0d65ffc41 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -1546,7 +1546,11 @@ void MainWindow::readSettings() { checkMpdDir(); Covers::self()->setSaveInMpdDir(Settings::self()->storeCoversInMpdDir()); - HttpServer::self()->setPort(Settings::self()->enableHttp() ? Settings::self()->httpPort() : 0); + if (Settings::self()->enableHttp()) { + HttpServer::self()->setDetails(Settings::self()->httpAddress(), Settings::self()->httpPort()); + } else { + HttpServer::self()->setDetails(QString(), 0); + } #ifdef ENABLE_DEVICES_SUPPORT deleteSongsAction->setVisible(Settings::self()->showDeleteAction()); #endif diff --git a/gui/settings.cpp b/gui/settings.cpp index b59aa327a..da461d1fe 100644 --- a/gui/settings.cpp +++ b/gui/settings.cpp @@ -512,6 +512,11 @@ int Settings::httpPort() return GET_INT("httpPort", 9001); } +QString Settings::httpAddress() +{ + return GET_STRING("httpAddress", QString()); +} + bool Settings::enableHttp() { return GET_BOOL("enableHttp", false); @@ -814,6 +819,11 @@ void Settings::saveHttpPort(int v) SET_VALUE("httpPort", v); } +void Settings::saveHttpAddress(const QString &v) +{ + SET_VALUE("httpAddress", v); +} + void Settings::saveEnableHttp(bool v) { SET_VALUE("enableHttp", v); diff --git a/gui/settings.h b/gui/settings.h index c3bf4257d..a8217ef82 100644 --- a/gui/settings.h +++ b/gui/settings.h @@ -102,6 +102,7 @@ public: int version(); int stopFadeDuration(); int httpPort(); + QString httpAddress(); bool enableHttp(); bool alwaysUseHttp(); bool playQueueGrouped(); @@ -159,6 +160,7 @@ public: #endif void saveStopFadeDuration(int v); void saveHttpPort(int v); + void saveHttpAddress(const QString &v); void saveEnableHttp(bool v); void saveAlwaysUseHttp(bool v); void savePlayQueueGrouped(bool v); diff --git a/http/httpserver.cpp b/http/httpserver.cpp index ef6891e5d..2c8ab9b01 100644 --- a/http/httpserver.cpp +++ b/http/httpserver.cpp @@ -60,9 +60,9 @@ void HttpServer::stop() } } -bool HttpServer::setPort(quint16 port) +bool HttpServer::setDetails(const QString &addr, quint16 port) { - if (socket && port==socket->port()) { + if (socket && port==socket->serverPort() && addr==socket->configuredAddress()) { return true; } @@ -78,7 +78,7 @@ bool HttpServer::setPort(quint16 port) if (0!=port) { thread=new QThread(0); - socket=new HttpSocket(port); + socket=new HttpSocket(addr, port); socket->moveToThread(thread); thread->start(); return socket->isListening(); @@ -94,7 +94,8 @@ bool HttpServer::isAlive() const QString HttpServer::address() const { - return QLatin1String("http://127.0.0.1:")+QString::number(socket ? socket->port() : Settings::self()->httpPort()); + return socket ? QLatin1String("http://")+socket->address()+QChar(':')+QString::number(socket->serverPort()) + : QLatin1String("http://127.0.0.1:")+QString::number(Settings::self()->httpPort()); } bool HttpServer::isOurs(const QString &url) const @@ -109,8 +110,8 @@ QByteArray HttpServer::encodeUrl(const Song &s) const } QUrl url; url.setScheme("http"); - url.setHost("127.0.0.1"); - url.setPort(socket->port()); + url.setHost(socket->address()); + url.setPort(socket->serverPort()); url.setPath(s.file); if (!s.album.isEmpty()) { url.addQueryItem("album", s.album); diff --git a/http/httpserver.h b/http/httpserver.h index 1b598e5bb..764a8b33e 100644 --- a/http/httpserver.h +++ b/http/httpserver.h @@ -46,7 +46,7 @@ public: void stop(); bool isAlive() const; - bool setPort(quint16 port); + bool setDetails(const QString &addr, quint16 port); QString address() const; bool isOurs(const QString &url) const; QByteArray encodeUrl(const Song &s) const; diff --git a/http/httpsocket.cpp b/http/httpsocket.cpp index 1859122e9..0965c34d7 100644 --- a/http/httpsocket.cpp +++ b/http/httpsocket.cpp @@ -23,17 +23,67 @@ #include "httpsocket.h" #include +#include #include #include #include #include +#include -HttpSocket::HttpSocket(quint16 p) +// static int level(const QString &s) +// { +// return QLatin1String("Link-local")==s +// ? 1 +// : QLatin1String("Site-local")==s +// ? 2 +// : QLatin1String("Global")==s +// ? 3 +// : 0; +// } + +HttpSocket::HttpSocket(const QString &addr, quint16 p) : QTcpServer(0) - , portNumber(p) + , cfgAddr(addr) , terminated(false) { - listen(QHostAddress::LocalHost, portNumber); + QHostAddress a; + if (!addr.isEmpty()) { + a=QHostAddress(addr); + + if (a.isNull()) { + QString ifaceName=addr; +// bool ipV4=true; +// +// if (ifaceName.endsWith("::6")) { +// ifaceName=ifaceName.left(ifaceName.length()-3); +// ipV4=false; +// } + + QNetworkInterface iface=QNetworkInterface::interfaceFromName(ifaceName); + if (iface.isValid()) { + QList addresses=iface.addressEntries(); +// int ip6Scope=-1; + foreach (const QNetworkAddressEntry &addr, addresses) { + QHostAddress ha=addr.ip(); + if (QAbstractSocket::IPv4Protocol==ha.protocol()) { +// if ((ipV4 && QAbstractSocket::IPv4Protocol==ha.protocol()) || (!ipV4 && QAbstractSocket::IPv6Protocol==ha.protocol())) { +// if (ipV4) { + a=ha; + break; +// } else { +// int scope=level(a.scopeId()); +// if (scope>ip6Scope) { +// ip6Scope=scope; +// a=ha; +// } +// } + } + } + } + } + } + listen(a.isNull() ? QHostAddress::LocalHost : a, p); + qWarning() << address(); } void HttpSocket::terminate() diff --git a/http/httpsocket.h b/http/httpsocket.h index 28fb0286e..b6e7bce31 100644 --- a/http/httpsocket.h +++ b/http/httpsocket.h @@ -31,15 +31,20 @@ class HttpSocket : public QTcpServer Q_OBJECT public: - HttpSocket(quint16 p); + HttpSocket(const QString &addr, quint16 p); virtual ~HttpSocket() { } void terminate(); void incomingConnection(int socket); - quint16 port() const { - return portNumber; + + QString address() const { + return serverAddress().toString(); + } + + QString configuredAddress() { + return cfgAddr; } private Q_SLOTS: @@ -47,7 +52,7 @@ private Q_SLOTS: void discardClient(); private: - quint16 portNumber; + QString cfgAddr; bool terminated; };