summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--common/config.cpp9
-rw-r--r--common/tools.cpp5
-rw-r--r--httptnt/deviceDescription.ecpp7
-rw-r--r--include/config.h30
-rw-r--r--include/contentDirectory.h1
-rw-r--r--include/server.h11
-rw-r--r--include/service.h1
-rw-r--r--include/tools.h3
-rw-r--r--include/webserver.h10
-rw-r--r--server/contentDirectory.cpp4
-rw-r--r--server/server.cpp76
-rw-r--r--server/service.cpp4
-rw-r--r--server/webserver.cpp53
-rw-r--r--upnp.cpp23
-rw-r--r--upnp.h1
16 files changed, 117 insertions, 122 deletions
diff --git a/Makefile b/Makefile
index 458be13..f8fc21e 100644
--- a/Makefile
+++ b/Makefile
@@ -66,6 +66,7 @@ OBJS = $(PLUGIN).o \
common/config.o \
common/tools.o \
common/parser.o \
+ common/setup.o \
media/profile.o \
media/mediaManager.o \
media/pluginManager.o \
diff --git a/common/config.cpp b/common/config.cpp
index ff24976..1668369 100644
--- a/common/config.cpp
+++ b/common/config.cpp
@@ -15,17 +15,20 @@ using namespace upnp;
upnp::cConfig::cConfig()
: enabled(true)
, expertSettings(false)
-, useInternalWebserver(false)
, webServerPort(0)
, presentationURL("index.html")
+, useLive(false)
+, livePort(8008)
, maxContentLength(KB(20))
, announceMaxAge(1800)
, deviceUUID(tools::GenerateUUIDRandomly())
-, serviceURL("services/")
-, staticContentURL("http/")
, bindToAddress(true)
, address("0.0.0.0")
, port(0)
, databaseFile("metadata.db")
{
}
+
+void upnp::cConfig::GenerateNewDeviceUUID(){
+ deviceUUID = tools::GenerateUUIDRandomly();
+}
diff --git a/common/tools.cpp b/common/tools.cpp
index 1b725e6..7ddfc4f 100644
--- a/common/tools.cpp
+++ b/common/tools.cpp
@@ -55,8 +55,8 @@ string GetNetworkInterfaceByIndex(int Index, bool skipLoop){
return GetNetworkInterfaces(skipLoop)[Index];
}
-vector<string> GetNetworkInterfaces(bool skipLoop){
- vector<string> interfaces;
+StringVector GetNetworkInterfaces(bool skipLoop){
+ StringVector interfaces;
int fd;
struct ifconf ifc;
@@ -457,3 +457,4 @@ IXML_Element* IxmlReplaceProperty(IXML_Document* document, IXML_Element* node, c
} // namespace ixml
} // namespace upnp
+
diff --git a/httptnt/deviceDescription.ecpp b/httptnt/deviceDescription.ecpp
index dfbe853..9646d30 100644
--- a/httptnt/deviceDescription.ecpp
+++ b/httptnt/deviceDescription.ecpp
@@ -23,7 +23,6 @@ using namespace upnp;
const upnp::cMediaServer::Description& serverDescription = server->GetServerDescription();
std::string deviceUUID = server->GetDeviceUUID();
- std::string urlBase = webserver.GetBaseUrl();
std::string presentationUrl = webserver.GetPresentationUrl();
std::string staticContentUrl = webserver.GetStaticContentUrl();
@@ -49,7 +48,7 @@ using namespace upnp;
<modelURL><$ serverDescription.modelURL $></modelURL>
<serialNumber><$ serverDescription.serialNumber $></serialNumber>
<UDN><$ deviceUUID $></UDN>
- <presentationURL><$ urlBase $><$ presentationUrl $></presentationURL>
+ <presentationURL><$ presentationUrl $></presentationURL>
<dlna:X_DLNADOC>DMS-1.50</dlna:X_DLNADOC>
<serviceList>
<{
@@ -62,7 +61,7 @@ using namespace upnp;
<service>
<serviceType><$ serviceDescription.serviceType $></serviceType>
<serviceId><$ serviceDescription.serviceID $></serviceId>
- <SCPDURL><$ urlBase $><$ serviceUrl $><$ serviceDescription.SCPDXML $></SCPDURL>
+ <SCPDURL><$ serviceUrl $><$ serviceDescription.SCPDXML $></SCPDURL>
<controlURL><$ controlUrl $><$ serviceDescription.controlDescriptor $></controlURL>
<eventSubURL><$ controlUrl $><$ serviceDescription.eventSubscriberDescriptor $></eventSubURL>
</service>
@@ -79,7 +78,7 @@ using namespace upnp;
<width><$ (*it).profile.width $></width>
<height><$ (*it).profile.height $></height>
<depth><$ (int)(*it).profile.bitDepth $></depth>
- <url><$ urlBase $><$ staticContentUrl $><$ (*it).filename $></url>
+ <url><$ staticContentUrl $><$ (*it).filename $></url>
</icon>
% };
</iconList>
diff --git a/include/config.h b/include/config.h
index b149316..187e46f 100644
--- a/include/config.h
+++ b/include/config.h
@@ -32,13 +32,7 @@ struct cConfig {
* debugging.
*/
bool expertSettings;
- /**
- * Use the internal web server
- *
- * If this is true, the internal web server is used for streaming of files.
- * Otherwise an external URL is used.
- */
- bool useInternalWebserver;
+
/**
* Web server root directory
*
@@ -46,12 +40,14 @@ struct cConfig {
* is empty, the default directory (plugins configuration folder) is used.
*/
string webServerRoot;
+
/**
* Web server port
*
* This is the port where the web server is listening on.
*/
uint16_t webServerPort;
+
/**
* External web server URL
*
@@ -59,6 +55,10 @@ struct cConfig {
* empty, the default presentation URL, which is /index.html is used.
*/
string presentationURL;
+
+ bool useLive;
+ uint16_t livePort;
+
/**
* Maximum size of SOAP messages
*
@@ -81,22 +81,9 @@ struct cConfig {
* it will be generated.
*/
string deviceUUID;
+ void GenerateNewDeviceUUID();
/**
- * Service URL
- *
- * This is the URL to the services and service descriptors of that services.
- */
- string serviceURL;
-
- /**
- * Static content URL
- *
- * This is the URL to the static content of the server. They must be located within the
- * network of the server.
- */
- string staticContentURL;
- /**
* Bind the server to an IP address
*
* If this is true, the media server is bound to the specified IP address,
@@ -106,6 +93,7 @@ struct cConfig {
string address;
string interface;
+
/**
* The media server listening port
*
diff --git a/include/contentDirectory.h b/include/contentDirectory.h
index c2edffc..92544a0 100644
--- a/include/contentDirectory.h
+++ b/include/contentDirectory.h
@@ -33,6 +33,7 @@ public:
virtual void SetError(Upnp_Action_Request* request, int error);
virtual void Init(cMediaServer* server, UpnpDevice_Handle deviceHandle);
+ virtual void Stop();
private:
int GetSearchCapabilities(Upnp_Action_Request* Request);
int GetSortCapabilities(Upnp_Action_Request* Request);
diff --git a/include/server.h b/include/server.h
index 349239c..3f24725 100644
--- a/include/server.h
+++ b/include/server.h
@@ -24,7 +24,7 @@ class cMediaServer {
public:
struct Description {
- Description(string, string, string , string, string, string , string, string);
+ Description(string, string, string , string, string, string , string, string, string);
string friendlyName;
string manufacturer;
string manufacturerURL;
@@ -33,6 +33,7 @@ public:
string modelNumber;
string modelURL;
string serialNumber;
+ string descriptionFile;
};
struct ServerIcon {
@@ -50,8 +51,6 @@ public:
bool Start();
bool Stop();
- bool IsRunning() const;
-
static cMediaServer* GetInstance();
void SetConfiguration(upnp::cConfig newConfig);
@@ -75,11 +74,6 @@ public:
static void RegisterService(cUPnPService* service);
private:
- class RuntimeException : public std::exception {
- public:
- virtual const char* what() const throw();
- };
-
cMediaServer();
string GetDeviceDescriptionUrl() const;
@@ -95,7 +89,6 @@ private:
UpnpDevice_Handle mDeviceHandle;
int mAnnounceMaxAge;
size_t mMaxContentLength;
- bool mIsRunning;
cWebserver* mWebserver;
cMediaManager* mMediaManager;
diff --git a/include/service.h b/include/service.h
index 07d3551..1ed4e91 100644
--- a/include/service.h
+++ b/include/service.h
@@ -33,6 +33,7 @@ public:
virtual ~cUPnPService();
virtual void Init(cMediaServer* server, UpnpDevice_Handle deviceHandle);
+ virtual void Stop();
virtual int Subscribe(
Upnp_Subscription_Request* Request ///< Information about the subscription
diff --git a/include/tools.h b/include/tools.h
index bd82cd4..e322adc 100644
--- a/include/tools.h
+++ b/include/tools.h
@@ -106,12 +106,13 @@ char* substr(const char* str, unsigned int offset, unsigned int length);
namespace upnp {
typedef std::list<std::string> StringList;
+ typedef std::vector<std::string> StringVector;
typedef std::map<std::string, uint32_t> IdList;
namespace tools {
string GetAddressByInterface(string Interface);
string GetNetworkInterfaceByIndex(int Index, bool skipLoop);
- vector<string> GetNetworkInterfaces(bool skipLoop);
+ StringVector GetNetworkInterfaces(bool skipLoop);
string ToString(long number);
diff --git a/include/webserver.h b/include/webserver.h
index 240d4d6..39ca8df 100644
--- a/include/webserver.h
+++ b/include/webserver.h
@@ -22,8 +22,8 @@ namespace upnp {
cWebserver(std::string address);
virtual ~cWebserver();
- void SetWebserverRootDir(std::string rootDirectory, std::string staticContentUrl, std::string presentationUrl);
- void SetServiceUrl(std::string descriptionUrl, std::string controlUrl);
+ void SetWebserverRootDir(std::string rootDirectory);
+ void SetPresentationUrl(std::string presentationUrl);
void SetListenerPort(uint16_t port);
@@ -47,14 +47,14 @@ namespace upnp {
std::string mListenerAddress;
uint16_t mListenerPort;
- std::string mServiceUrl;
- std::string mControlUrl;
- std::string mStaticContentUrl;
std::string mPresentationUrl;
+ std::string mStaticContentUrl;
+ std::string mServiceUrl;
class cWSThread : public cThread {
public:
cWSThread(cWebserver& webServer);
+ void Stop();
virtual void Action(void);
private:
cWebserver& mWebserver;
diff --git a/server/contentDirectory.cpp b/server/contentDirectory.cpp
index b7d11ce..c014804 100644
--- a/server/contentDirectory.cpp
+++ b/server/contentDirectory.cpp
@@ -108,6 +108,10 @@ void cContentDirectory::Action(){
}
}
+void cContentDirectory::Stop(){
+ this->Cancel(2);
+}
+
int cContentDirectory::Execute(Upnp_Action_Request* request){
if (request == NULL) {
esyslog("UPnP\tCMS Action Handler - request is null");
diff --git a/server/server.cpp b/server/server.cpp
index 32c584d..acfe7a1 100644
--- a/server/server.cpp
+++ b/server/server.cpp
@@ -27,11 +27,11 @@ cMediaServer::serviceMap cMediaServer::mServices;
cMediaServer::cMediaServer()
: mServerDescription("VDR UPnP/DLNA MS", "Denis Loh", "http://upnp.vdr-developer.org",
DESCRIPTION, "VDR UPnP-DLNA MS", VERSION,
- "http://projects.vdr-developer.org/projects/plg-upnp/files", VERSION)
+ "http://projects.vdr-developer.org/projects/plg-upnp/files", VERSION,
+ "deviceDescription.xml")
, mDeviceHandle(0)
, mAnnounceMaxAge(1800)
, mMaxContentLength(KB(20))
-, mIsRunning(false)
, mWebserver(NULL)
, mMediaManager(NULL)
{
@@ -46,10 +46,6 @@ cMediaServer::~cMediaServer(){
delete mMediaManager;
}
-bool cMediaServer::IsRunning() const {
- return mIsRunning;
-}
-
bool cMediaServer::Start(){
isyslog("UPnP\tStarting UPnP media server");
@@ -114,19 +110,20 @@ bool cMediaServer::Start(){
return false;
}
-
-
- mIsRunning = true;
-
- return IsRunning();
+ return true;
}
bool cMediaServer::Stop(){
- isyslog("UPnP\tStopping UPnP media server");
-
int ret = 0;
+ isyslog("UPnP\tStopping services...");
+ for(serviceMap::iterator it = cMediaServer::mServices.begin(); it != cMediaServer::mServices.end(); ++it){
+ isyslog("UPnP\t...%s", (*it).second->GetServiceDescription().serviceType.c_str());
+ (*it).second->Stop();
+ }
+
+ isyslog("UPnP\tStopping UPnP media server");
UpnpUnRegisterRootDevice(mDeviceHandle);
if (ret != UPNP_E_SUCCESS) {
esyslog("UPnP\tError while sending first advertisments - Errorcode: %d", ret);
@@ -135,6 +132,7 @@ bool cMediaServer::Stop(){
UpnpFinish();
+ isyslog("UPnP\tStopping web server...");
if(mWebserver){
mWebserver->Stop();
@@ -147,23 +145,32 @@ bool cMediaServer::Stop(){
mMediaManager = NULL;
}
- mIsRunning = false;
-
- return !IsRunning();
+ return true;
}
bool cMediaServer::Initialize(){
- isyslog("UPnP\tInitializing UPnP media server");
+ string address;
+ uint16_t port = 0;
+
+ if(mCurrentConfiguration.expertSettings){
+ address = mCurrentConfiguration.bindToAddress
+ ? mCurrentConfiguration.address
+ : tools::GetAddressByInterface(mCurrentConfiguration.interface);
- string address = mCurrentConfiguration.bindToAddress
- ? mCurrentConfiguration.address
- : tools::GetAddressByInterface(mCurrentConfiguration.interface);
+ if(address.empty() || !address.compare("0.0.0.0")){
+ address = tools::GetAddressByInterface(tools::GetNetworkInterfaceByIndex(0, true));
+ }
- if(!address.compare("0.0.0.0"))
+ port = mCurrentConfiguration.port;
+ } else {
address = tools::GetAddressByInterface(tools::GetNetworkInterfaceByIndex(0, true));
+ port = 0;
+ }
int ret = 0;
+ isyslog("UPnP\tInitializing UPnP media server on %s:%d", address.c_str(), port);
+
ret = UpnpInit(address.c_str(), mCurrentConfiguration.port);
if(ret != UPNP_E_SUCCESS && ret != UPNP_E_INIT){
@@ -182,9 +189,21 @@ bool cMediaServer::Initialize(){
SetAnnounceMaxAge(mCurrentConfiguration.announceMaxAge);
if(!mCurrentConfiguration.webServerRoot.empty())
- mWebserver->SetWebserverRootDir(mCurrentConfiguration.webServerRoot,
- mCurrentConfiguration.staticContentURL,
- mCurrentConfiguration.presentationURL);
+ mWebserver->SetWebserverRootDir(mCurrentConfiguration.webServerRoot);
+
+ if(!mCurrentConfiguration.useLive){
+ if(!mCurrentConfiguration.presentationURL.empty())
+ mWebserver->SetPresentationUrl(mCurrentConfiguration.presentationURL);
+ } else {
+ stringstream ss;
+
+ uint16_t port = mCurrentConfiguration.livePort ? mCurrentConfiguration.livePort : 8008;
+
+ ss << "http://" << GetServerIPAddress() << ":" << port << "/";
+
+ mWebserver->SetPresentationUrl(ss.str());
+ }
+
if(mCurrentConfiguration.webServerPort)
mWebserver->SetListenerPort(mCurrentConfiguration.webServerPort);
@@ -239,7 +258,7 @@ uint16_t cMediaServer::GetServerPort() const {
}
string cMediaServer::GetDeviceDescriptionUrl() const {
- return mWebserver->GetBaseUrl() + mCurrentConfiguration.serviceURL + "deviceDescription.xml";
+ return mWebserver->GetServiceUrl() + mServerDescription.descriptionFile;
}
void cMediaServer::RegisterService(cUPnPService* service){
@@ -309,10 +328,6 @@ int cMediaServer::ActionCallback(Upnp_EventType eventtype, void *event, void *co
}
-const char* cMediaServer::RuntimeException::what() const throw() {
- return "Runtime error: media server is not running";
-}
-
bool cMediaServer::CheckDeviceUUID(string deviceUUID) const {
return deviceUUID.find(mCurrentConfiguration.deviceUUID) != string::npos;
}
@@ -320,7 +335,7 @@ bool cMediaServer::CheckDeviceUUID(string deviceUUID) const {
cMediaServer::Description::Description(
string fn, string m, string murl,
string mod, string mon, string mono,
- string mourl, string sno)
+ string mourl, string sno, string desc)
: friendlyName(fn)
, manufacturer(m)
, manufacturerURL(murl)
@@ -329,6 +344,7 @@ cMediaServer::Description::Description(
, modelNumber(mono)
, modelURL(mourl)
, serialNumber(sno)
+, descriptionFile(desc)
{
}
diff --git a/server/service.cpp b/server/service.cpp
index 14a0bb6..d127e59 100644
--- a/server/service.cpp
+++ b/server/service.cpp
@@ -28,6 +28,10 @@ void cUPnPService::Init(cMediaServer* server, UpnpDevice_Handle deviceHandle){
mDeviceHandle = deviceHandle;
}
+void cUPnPService::Stop(){
+ return;
+}
+
void cUPnPService::SetError(Upnp_Action_Request* request, int error){
request->ErrCode = error;
switch(error){
diff --git a/server/webserver.cpp b/server/webserver.cpp
index b67076b..d2a25f0 100644
--- a/server/webserver.cpp
+++ b/server/webserver.cpp
@@ -8,20 +8,24 @@
#include "../include/webserver.h"
#include "../upnp.h"
#include <sstream>
+#include <tnt/job.h>
namespace upnp {
cWebserver::cWebserver(std::string address)
: mListenerAddress(address)
, mListenerPort(7649)
+, mStaticContentUrl("http/")
+, mServiceUrl("services/")
, mWebserverThread(*this)
{
- SetWebserverRootDir(string(), string(), string());
- SetServiceUrl(string(), string());
+ SetWebserverRootDir(string());
+ SetPresentationUrl(string());
}
cWebserver::~cWebserver(){
-
+ mApplication.shutdown();
+ mWebserverThread.Stop();
}
bool cWebserver::Start(){
@@ -87,18 +91,17 @@ void cWebserver::SetListenerPort(uint16_t port){
mListenerPort = port ? port : 7649;
}
-void cWebserver::SetWebserverRootDir(std::string rootDirectory, std::string staticContentUrl, std::string presentationUrl){
+void cWebserver::SetWebserverRootDir(std::string rootDirectory){
if(mWebserverThread.Active()) return;
if(rootDirectory.empty())
mWebserverRootDir = std::string(cPluginUpnp::ConfigDirectory(PLUGIN_NAME_I18N)) + "/httpdocs/";
else
mWebserverRootDir = rootDirectory;
+}
- if(staticContentUrl.empty())
- mStaticContentUrl = "http/";
- else
- mStaticContentUrl = staticContentUrl;
+void cWebserver::SetPresentationUrl(std::string presentationUrl){
+ if(mWebserverThread.Active()) return;
if(presentationUrl.empty())
mPresentationUrl = "index.html";
@@ -106,25 +109,6 @@ void cWebserver::SetWebserverRootDir(std::string rootDirectory, std::string stat
mPresentationUrl = presentationUrl;
}
-void cWebserver::SetServiceUrl(std::string descriptionUrl, std::string controlUrl){
- if(mWebserverThread.Active()) return;
-
- if(descriptionUrl.empty()){
- mServiceUrl = "services/";
- }
- else
- mServiceUrl = descriptionUrl;
-
- if(controlUrl.empty()){
- stringstream s;
- s << "http://" << UpnpGetServerIpAddress() << ":" << UpnpGetServerPort() << "/" << "services/";
-
- mControlUrl = s.str();
- } else {
- mControlUrl = controlUrl;
- }
-}
-
const std::string cWebserver::GetBaseUrl() const {
stringstream s;
s << "http://" << mListenerAddress << ":" << mListenerPort << "/";
@@ -133,25 +117,26 @@ const std::string cWebserver::GetBaseUrl() const {
}
const std::string cWebserver::GetServiceUrl() const {
- return mServiceUrl;
+ return GetBaseUrl() + mServiceUrl;
}
const std::string cWebserver::GetControlUrl() const {
- return mControlUrl;
+ stringstream s;
+ s << "http://" << UpnpGetServerIpAddress() << ":" << UpnpGetServerPort() << "/" << "services/";
+ return s.str();
}
const std::string cWebserver::GetPresentationUrl() const {
- return mPresentationUrl;
+ return (mPresentationUrl.find("http://",0) == 0) ? mPresentationUrl : (GetBaseUrl() + mPresentationUrl);
}
const std::string cWebserver::GetStaticContentUrl() const {
- return mStaticContentUrl;
+ return GetBaseUrl() + mStaticContentUrl;
}
cWebserver::cWSThread::cWSThread(cWebserver& webServer)
: mWebserver(webServer)
{
-
}
void cWebserver::cWSThread::Action(){
@@ -162,6 +147,10 @@ void cWebserver::cWSThread::Action(){
}
}
+void cWebserver::cWSThread::Stop(){
+ Cancel(5);
+}
+
} // namespace upnp
diff --git a/upnp.cpp b/upnp.cpp
index 63064f4..7bcaf20 100644
--- a/upnp.cpp
+++ b/upnp.cpp
@@ -8,7 +8,7 @@
#include <iostream>
#include "upnp.h"
-#include "include/connection.h"
+#include "include/setup.h"
using namespace std;
using namespace upnp;
@@ -64,27 +64,22 @@ void cPluginUpnp::MainThreadHook(void)
// WARNING: Use with great care - see PLUGINS.html!
}
-cString cPluginUpnp::Active(void)
-{
- // Return a message string if shutdown should be postponed
- if(mMediaServer->IsRunning()){
- isyslog("UPnP\tPlugin is still active. Shutdown is postponed.");
- return tr("The UPnP server is still running.");
- }
-
- return NULL;
-}
-
cMenuSetupPage *cPluginUpnp::SetupMenu(void)
{
// Return a setup menu in case the plugin supports one.
- return NULL;
+ return new cMenuSetupUPnP();
}
bool cPluginUpnp::SetupParse(const char *Name, const char *Value)
{
// Parse your own setup parameters and store their values.
- return false;
+ upnp::cConfig config = mMediaServer->GetConfiguration();
+
+ if(!cMenuSetupUPnP::SetupParse(Name, Value, config)) return false;
+
+ mMediaServer->SetConfiguration(config);
+
+ return true;
}
VDRPLUGINCREATOR(cPluginUpnp); // Don't touch this!
diff --git a/upnp.h b/upnp.h
index a2d54de..d0e3bd0 100644
--- a/upnp.h
+++ b/upnp.h
@@ -32,7 +32,6 @@ public:
virtual void Stop(void);
virtual void Housekeeping(void);
virtual void MainThreadHook(void);
- virtual cString Active(void);
virtual cMenuSetupPage *SetupMenu(void);
virtual bool SetupParse(const char *Name, const char *Value);
};