MythTV  master
mediaserver.cpp
Go to the documentation of this file.
1 // Program Name: mediaserver.cpp
3 //
4 // Purpose - uPnp Media Server main Class
5 //
6 // Created By : David Blain Created On : Jan. 15, 2007
7 // Modified By : Modified On:
8 //
10 
11 #include "mediaserver.h"
12 #include "httpconfig.h"
13 #include "internetContent.h"
14 #include "mythdirs.h"
15 #include "htmlserver.h"
16 
17 #include "upnpcdstv.h"
18 #include "upnpcdsmusic.h"
19 #include "upnpcdsvideo.h"
20 
21 #include <QScriptEngine>
22 #include <QNetworkProxy>
23 #include <QNetworkInterface>
24 
34 
35 #ifdef USING_LIBDNS_SD
36 #include "bonjourregister.h"
37 #endif
38 
41 //
42 // UPnp Class implementaion
43 //
46 
48 //
50 
52  m_sSharePath(GetShareDir())
53 {
54  LOG(VB_UPNP, LOG_INFO, "MediaServer(): Begin");
55 
56  // ----------------------------------------------------------------------
57  // Initialize Configuration class (Database for Servers)
58  // ----------------------------------------------------------------------
59 
61 
62  // ----------------------------------------------------------------------
63  // Create mini HTTP Server
64  // ----------------------------------------------------------------------
65 
66  LOG(VB_UPNP, LOG_INFO, "MediaServer(): End");
67 }
68 
69 void MediaServer::Init(bool bIsMaster, bool bDisableUPnp /* = false */)
70 {
71  LOG(VB_UPNP, LOG_INFO, "MediaServer::Init(): Begin");
72 
73  int nPort = g_pConfig->GetValue( "BackendStatusPort", 6544 );
74  int nSSLPort = g_pConfig->GetValue( "BackendSSLPort", (g_pConfig->GetValue( "BackendStatusPort", 6544 ) + 10) );
75  int nWSPort = (g_pConfig->GetValue( "BackendStatusPort", 6544 ) + 5);
76 
77  HttpServer *pHttpServer = new HttpServer();
78 
79  if (!pHttpServer->isListening())
80  {
81  pHttpServer->setProxy(QNetworkProxy::NoProxy);
82  // HTTP
83  if (!pHttpServer->listen(nPort))
84  {
85  LOG(VB_GENERAL, LOG_ERR, "MediaServer: HttpServer Create Error");
86  delete pHttpServer;
87  pHttpServer = nullptr;
88  return;
89  }
90 
91 #ifndef QT_NO_OPENSSL
92  // HTTPS (SSL)
93  if (!pHttpServer->listen(nSSLPort, true, kSSLServer))
94  {
95  LOG(VB_GENERAL, LOG_ERR, "MediaServer: HttpServer failed to create SSL server");
96  }
97 #endif
98  }
99 
101 
103  {
104  if (!m_webSocketServer->listen(nWSPort))
105  {
106  LOG(VB_GENERAL, LOG_ERR, "MediaServer: WebSocketServer Create Error");
107  }
108  }
109 
110  QString sFileName = g_pConfig->GetValue( "upnpDescXmlPath",
111  m_sSharePath );
112 
113  if ( bIsMaster )
114  sFileName += "devicemaster.xml";
115  else
116  sFileName += "deviceslave.xml";
117 
118  // ------------------------------------------------------------------
119  // Make sure our device Description is loaded.
120  // ------------------------------------------------------------------
121 
122  LOG(VB_UPNP, LOG_INFO,
123  "MediaServer: Loading UPnp Description " + sFileName);
124 
125  g_UPnpDeviceDesc.Load( sFileName );
126 
127  // ------------------------------------------------------------------
128  // Register Http Server Extensions...
129  // ------------------------------------------------------------------
130 
131  LOG(VB_UPNP, LOG_INFO, "MediaServer: Registering Http Server Extensions.");
132 
133  HtmlServerExtension *pHtmlServer;
134  pHtmlServer = new HtmlServerExtension(m_sSharePath + "html", "backend_");
135  pHttpServer->RegisterExtension( pHtmlServer );
136  pHttpServer->RegisterExtension( new HttpConfig() );
137  pHttpServer->RegisterExtension( new InternetContent ( m_sSharePath ));
138 
139  pHttpServer->RegisterExtension( new MythServiceHost ( m_sSharePath ));
140  pHttpServer->RegisterExtension( new GuideServiceHost ( m_sSharePath ));
141  pHttpServer->RegisterExtension( new ContentServiceHost( m_sSharePath ));
142  pHttpServer->RegisterExtension( new DvrServiceHost ( m_sSharePath ));
143  pHttpServer->RegisterExtension( new ChannelServiceHost( m_sSharePath ));
144  pHttpServer->RegisterExtension( new VideoServiceHost ( m_sSharePath ));
145  pHttpServer->RegisterExtension( new MusicServiceHost ( m_sSharePath ));
146  pHttpServer->RegisterExtension( new CaptureServiceHost( m_sSharePath ));
147  pHttpServer->RegisterExtension( new ImageServiceHost ( m_sSharePath ));
148 
149 
150  // ------------------------------------------------------------------
151  // Register Service Types with Scripting Engine
152  //
153  // -=>NOTE: We need to know the actual type at compile time for this
154  // to work, so it needs to be done here. I'm still looking
155  // into ways that we may encapsulate this in the service
156  // classes. - dblain
157  // ------------------------------------------------------------------
158 
159  QScriptEngine* pEngine = pHtmlServer->ScriptEngine();
160 
161  pEngine->globalObject().setProperty("Myth" ,
162  pEngine->scriptValueFromQMetaObject< ScriptableMyth >() );
163  pEngine->globalObject().setProperty("Guide" ,
164  pEngine->scriptValueFromQMetaObject< ScriptableGuide >() );
165  pEngine->globalObject().setProperty("Content",
166  pEngine->scriptValueFromQMetaObject< ScriptableContent >() );
167  pEngine->globalObject().setProperty("Dvr" ,
168  pEngine->scriptValueFromQMetaObject< ScriptableDvr >() );
169  pEngine->globalObject().setProperty("Channel",
170  pEngine->scriptValueFromQMetaObject< ScriptableChannel >() );
171  pEngine->globalObject().setProperty("Video" ,
172  pEngine->scriptValueFromQMetaObject< ScriptableVideo >() );
173  pEngine->globalObject().setProperty("Music" ,
174  pEngine->scriptValueFromQMetaObject< ScriptableVideo >() );
175  pEngine->globalObject().setProperty("Capture" ,
176  pEngine->scriptValueFromQMetaObject< ScriptableCapture >() );
177  pEngine->globalObject().setProperty("Image" ,
178  pEngine->scriptValueFromQMetaObject< ScriptableImage >() );
179 
180  // ------------------------------------------------------------------
181 
182  if (bDisableUPnp)
183  {
184  LOG(VB_GENERAL, LOG_NOTICE,
185  "*** The UPNP service has been DISABLED with the "
186  "--noupnp option ***");
187  return;
188  }
189 
190  QList<QHostAddress> IPAddrList = ServerPool::DefaultListen();
191  if (IPAddrList.contains(QHostAddress(QHostAddress::AnyIPv4)))
192  {
193  IPAddrList.removeAll(QHostAddress(QHostAddress::AnyIPv4));
194  IPAddrList.removeAll(QHostAddress(QHostAddress::AnyIPv6));
195  IPAddrList.append(QNetworkInterface::allAddresses());
196  }
197 
198  if (IPAddrList.isEmpty())
199  {
200  LOG(VB_GENERAL, LOG_ERR,
201  "MediaServer: No Listenable IP Addresses found - "
202  "Disabling UPnP");
203  return;
204  }
205 
206  // ----------------------------------------------------------------------
207  // Initialize UPnp Stack
208  // ----------------------------------------------------------------------
209 
210  if (Initialize( IPAddrList, nPort, pHttpServer ))
211  {
212 
213  // ------------------------------------------------------------------
214  // Register any HttpServerExtensions... Only The Master Backend
215  // ------------------------------------------------------------------
216 
217  if (bIsMaster)
218  {
219  QString sSourceProtocols = GetSourceProtocolInfos().join(",");
220 
221  LOG(VB_UPNP, LOG_INFO, "MediaServer: Registering MS_MediaReceiverRegistrar Service.");
222 
224  m_sSharePath ) );
225 
226  LOG(VB_UPNP, LOG_INFO, "MediaServer: Registering ConnnectionManager Service.");
227 
229  m_sSharePath, sSourceProtocols );
231 
232  LOG(VB_UPNP, LOG_INFO, "MediaServer: Registering ContentDirectory Service.");
233 
236 
237  // ----------------------------------------------------------------
238  // Register CDS Extensions
239  // ----------------------------------------------------------------
240 
241  LOG(VB_UPNP, LOG_INFO,
242  "MediaServer: Registering UPnpCDSTv Extension");
243 
245 
246  LOG(VB_UPNP, LOG_INFO,
247  "MediaServer: Registering UPnpCDSMusic Extension");
248 
250 
251  LOG(VB_UPNP, LOG_INFO,
252  "MediaServer: Registering UPnpCDSVideo Extension");
253 
255  }
256 
257 #if 0
258  LOG(VB_UPNP, LOG_INFO, "MediaServer::Adding Context Listener");
259 
260  gCoreContext->addListener( this );
261 #endif
262 
263  Start();
264 
265 #ifdef USING_LIBDNS_SD
266  // advertise using Bonjour
267  if (gCoreContext)
268  {
269  m_bonjour = new BonjourRegister();
270  if (m_bonjour)
271  {
272  QByteArray name("Mythbackend on ");
273  name.append(gCoreContext->GetHostName());
274  QByteArray txt(bIsMaster ? "\x06master" : "\x05slave");
275  m_bonjour->Register(nPort, "_mythbackend._tcp", name, txt);
276  }
277  }
278 #endif
279  }
280 
281  LOG(VB_UPNP, LOG_INFO, "MediaServer::Init(): End");
282 }
283 
285 //
287 
289 {
290  // -=>TODO: Need to check to see if calling this more than once is ok.
291 
292 #if 0
294 #endif
295 
296  delete m_webSocketServer;
297  delete m_pHttpServer;
298 
299 #ifdef USING_LIBDNS_SD
300  delete m_bonjour;
301 #endif
302 }
303 
305 //
307 #if 0
308 void MediaServer::customEvent( QEvent *e )
309 {
310  if (MythEvent::Type(e->type()) == MythEvent::MythEventMessage)
311  {
312  MythEvent *me = static_cast<MythEvent *>(e);
313  QString message = me->Message();
314 
315  //-=>TODO: Need to handle events to notify clients of changes
316  }
317 }
318 #endif
319 //
322 
324 {
325  m_pUPnpCDS->RegisterExtension( pExtension );
326 }
327 
329 //
331 
333 {
334  m_pUPnpCDS->UnregisterExtension( pExtension );
335 }
void RegisterExtension(UPnpCDSExtension *pExtension)
Definition: upnpcds.cpp:168
UPnpCMGR * m_pUPnpCMGR
Definition: mediaserver.h:44
WebSocketServer * m_webSocketServer
Definition: mediaserver.h:39
virtual int GetValue(const QString &sSetting, int Default)=0
static Configuration * g_pConfig
Definition: upnp.h:100
bool listen(QList< QHostAddress > addrs, quint16 port, bool requireall=true, PoolServerType type=kTCPServer)
Definition: serverpool.cpp:380
bool Initialize(int nServicePort, HttpServer *pHttpServer)
Definition: upnp.cpp:86
static Type MythEventMessage
Definition: mythevent.h:66
void UnregisterExtension(UPnpCDSExtension *pExtension)
Definition: upnpcds.cpp:187
void removeListener(QObject *listener)
Remove a listener to the observable.
UPnpDevice * RootDevice()
Definition: upnp.h:127
void setProxy(const QNetworkProxy &proxy)
Definition: serverpool.h:98
void RegisterExtension(HttpServerExtension *)
Definition: httpserver.cpp:325
QString m_sSharePath
Definition: mediaserver.h:46
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
virtual ~MediaServer()
void addListener(QObject *listener)
Add a listener to the observable.
This class is used as a container for messages.
Definition: mythevent.h:16
QString GetShareDir(void)
Definition: mythdirs.cpp:222
HttpServer * m_pHttpServer
Definition: upnp.h:102
const char * name
Definition: ParseText.cpp:328
virtual void Start()
Definition: upnp.cpp:163
The WebSocket server, which listens for connections.
Definition: websocket.h:37
void UnregisterExtension(UPnpCDSExtension *pExtension)
static void SetConfiguration(Configuration *pConfig)
Definition: upnp.cpp:61
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
QScriptEngine * ScriptEngine()
Definition: htmlserver.h:47
void Init(bool bIsMaster, bool bDisableUPnp=false)
Definition: mediaserver.cpp:69
QStringList GetSourceProtocolInfos()
Return a QStringList containing the supported Source Protocols.
Definition: upnputil.cpp:126
UPnpCDS * m_pUPnpCDS
Definition: mediaserver.h:43
bool Load(const QString &sFileName)
Definition: upnpdevice.cpp:43
bool isListening(void)
Definition: serverpool.h:92
static QList< QHostAddress > DefaultListen(void)
Definition: serverpool.cpp:289
const QString & Message() const
Definition: mythevent.h:58
QString GetHostName(void)
void RegisterExtension(UPnpCDSExtension *pExtension)
static UPnpDeviceDesc g_UPnpDeviceDesc
Definition: upnp.h:107