diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | common/config.cpp | 9 | ||||
-rw-r--r-- | common/tools.cpp | 5 | ||||
-rw-r--r-- | httptnt/deviceDescription.ecpp | 7 | ||||
-rw-r--r-- | include/config.h | 30 | ||||
-rw-r--r-- | include/contentDirectory.h | 1 | ||||
-rw-r--r-- | include/server.h | 11 | ||||
-rw-r--r-- | include/service.h | 1 | ||||
-rw-r--r-- | include/tools.h | 3 | ||||
-rw-r--r-- | include/webserver.h | 10 | ||||
-rw-r--r-- | server/contentDirectory.cpp | 4 | ||||
-rw-r--r-- | server/server.cpp | 76 | ||||
-rw-r--r-- | server/service.cpp | 4 | ||||
-rw-r--r-- | server/webserver.cpp | 53 | ||||
-rw-r--r-- | upnp.cpp | 23 | ||||
-rw-r--r-- | upnp.h | 1 |
16 files changed, 117 insertions, 122 deletions
@@ -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 @@ -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! @@ -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); }; |