Merge pull request #4857 from t-nelson/Gotham_13.2_backports
[vuplus_xbmc] / xbmc / network / NetworkServices.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "NetworkServices.h"
22 #include "Application.h"
23 #include "ApplicationMessenger.h"
24 #include "GUIInfoManager.h"
25 #ifdef TARGET_LINUX
26 #include "Util.h"
27 #endif
28 #include "dialogs/GUIDialogKaiToast.h"
29 #include "dialogs/GUIDialogOK.h"
30 #include "dialogs/GUIDialogYesNo.h"
31 #include "guilib/LocalizeStrings.h"
32 #include "network/Network.h"
33
34 #ifdef HAS_AIRPLAY
35 #include "network/AirPlayServer.h"
36 #endif // HAS_AIRPLAY
37
38 #ifdef HAS_AIRTUNES
39 #include "network/AirTunesServer.h"
40 #endif // HAS_AIRTUNES
41
42 #ifdef HAS_EVENT_SERVER
43 #include "network/EventServer.h"
44 #endif // HAS_EVENT_SERVER
45
46 #ifdef HAS_JSONRPC
47 #include "interfaces/json-rpc/JSONRPC.h"
48 #include "network/TCPServer.h"
49 #endif
50
51 #ifdef HAS_ZEROCONF
52 #include "network/Zeroconf.h"
53 #endif // HAS_ZEROCONF
54
55 #ifdef HAS_UPNP
56 #include "network/upnp/UPnP.h"
57 #endif // HAS_UPNP
58
59 #ifdef HAS_WEB_SERVER
60 #include "network/WebServer.h"
61 #include "network/httprequesthandler/HTTPImageHandler.h"
62 #include "network/httprequesthandler/HTTPVfsHandler.h"
63 #ifdef HAS_JSONRPC
64 #include "network/httprequesthandler/HTTPJsonRpcHandler.h"
65 #endif // HAS_JSONRPC
66 #ifdef HAS_WEB_INTERFACE
67 #include "network/httprequesthandler/HTTPWebinterfaceHandler.h"
68 #include "network/httprequesthandler/HTTPWebinterfaceAddonsHandler.h"
69 #endif // HAS_WEB_INTERFACE
70 #endif // HAS_WEB_SERVER
71
72 #if defined(TARGET_DARWIN_OSX)
73 #include "osx/XBMCHelper.h"
74 #endif
75
76 #include "settings/AdvancedSettings.h"
77 #include "settings/lib/Setting.h"
78 #include "settings/Settings.h"
79 #include "utils/log.h"
80 #include "utils/RssManager.h"
81
82 using namespace std;
83 #ifdef HAS_JSONRPC
84 using namespace JSONRPC;
85 #endif // HAS_JSONRPC
86 #ifdef HAS_EVENT_SERVER
87 using namespace EVENTSERVER;
88 #endif // HAS_EVENT_SERVER
89 #ifdef HAS_UPNP
90 using namespace UPNP;
91 #endif // HAS_UPNP
92
93 CNetworkServices::CNetworkServices()
94 #ifdef HAS_WEB_SERVER
95   :
96   m_webserver(*new CWebServer),
97   m_httpImageHandler(*new CHTTPImageHandler),
98   m_httpVfsHandler(*new CHTTPVfsHandler)
99 #ifdef HAS_JSONRPC
100   , m_httpJsonRpcHandler(*new CHTTPJsonRpcHandler)
101 #endif // HAS_JSONRPC
102 #ifdef HAS_WEB_INTERFACE
103   , m_httpWebinterfaceHandler(*new CHTTPWebinterfaceHandler)
104   , m_httpWebinterfaceAddonsHandler(*new CHTTPWebinterfaceAddonsHandler)
105 #endif // HAS_WEB_INTERFACE
106 #endif // HAS_WEB_SERVER
107 {
108 #ifdef HAS_WEB_SERVER
109   CWebServer::RegisterRequestHandler(&m_httpImageHandler);
110   CWebServer::RegisterRequestHandler(&m_httpVfsHandler);
111 #ifdef HAS_JSONRPC
112   CWebServer::RegisterRequestHandler(&m_httpJsonRpcHandler);
113 #endif // HAS_JSONRPC
114 #ifdef HAS_WEB_INTERFACE
115   CWebServer::RegisterRequestHandler(&m_httpWebinterfaceAddonsHandler);
116   CWebServer::RegisterRequestHandler(&m_httpWebinterfaceHandler);
117 #endif // HAS_WEB_INTERFACE
118 #endif // HAS_WEB_SERVER
119 }
120
121 CNetworkServices::~CNetworkServices()
122 {
123 #ifdef HAS_WEB_SERVER
124   CWebServer::UnregisterRequestHandler(&m_httpImageHandler);
125   delete &m_httpImageHandler;
126   CWebServer::UnregisterRequestHandler(&m_httpVfsHandler);
127   delete &m_httpVfsHandler;
128 #ifdef HAS_JSONRPC
129   CWebServer::UnregisterRequestHandler(&m_httpJsonRpcHandler);
130   delete &m_httpJsonRpcHandler;
131   CJSONRPC::Cleanup();
132 #endif // HAS_JSONRPC
133 #ifdef HAS_WEB_INTERFACE
134   CWebServer::UnregisterRequestHandler(&m_httpWebinterfaceAddonsHandler);
135   delete &m_httpWebinterfaceAddonsHandler;
136   CWebServer::UnregisterRequestHandler(&m_httpWebinterfaceHandler);
137   delete &m_httpWebinterfaceHandler;
138 #endif // HAS_WEB_INTERFACE
139   delete &m_webserver;
140 #endif // HAS_WEB_SERVER
141 }
142
143 CNetworkServices& CNetworkServices::Get()
144 {
145   static CNetworkServices sNetworkServices;
146   return sNetworkServices;
147 }
148
149 bool CNetworkServices::OnSettingChanging(const CSetting *setting)
150 {
151   if (setting == NULL)
152     return false;
153
154   const std::string &settingId = setting->GetId();
155 #ifdef HAS_WEB_SERVER
156   if (settingId == "services.webserver" ||
157       settingId == "services.webserverport")
158   {
159     if (IsWebserverRunning() && !StopWebserver())
160       return false;
161
162     if (CSettings::Get().GetBool("services.webserver"))
163     {
164       if (!StartWebserver())
165       {
166         CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33101), "", g_localizeStrings.Get(33100), "");
167         return false;
168       }
169     }
170   }
171   else if (settingId == "services.esport" ||
172            settingId == "services.webserverport")
173     return ValidatePort(((CSettingInt*)setting)->GetValue());
174   else
175 #endif // HAS_WEB_SERVER
176
177 #ifdef HAS_ZEROCONF
178   if (settingId == "services.zeroconf")
179   {
180     if (((CSettingBool*)setting)->GetValue())
181       return StartZeroconf();
182 #ifdef HAS_AIRPLAY
183     else
184     {
185       // cannot disable 
186       if (IsAirPlayServerRunning() || IsAirTunesServerRunning())
187       {
188         CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(1259), g_localizeStrings.Get(34303), g_localizeStrings.Get(34304), "");
189         return false;
190       }
191
192       return StopZeroconf();
193     }
194 #endif // HAS_AIRPLAY
195   }
196   else
197 #endif // HAS_ZEROCONF
198
199 #ifdef HAS_AIRPLAY
200   if (settingId == "services.airplay")
201   {
202     if (((CSettingBool*)setting)->GetValue())
203     {
204 #ifdef HAS_ZEROCONF
205       // AirPlay needs zeroconf
206       if (!CSettings::Get().GetBool("services.zeroconf"))
207       {
208         CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(1273), g_localizeStrings.Get(33100), g_localizeStrings.Get(34302), "");
209         return false;
210       }
211 #endif //HAS_ZEROCONF
212
213       // note - airtunesserver has to start before airplay server (ios7 client detection bug)
214 #ifdef HAS_AIRTUNES
215       if (!StartAirTunesServer())
216       {
217         CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(1274), "", g_localizeStrings.Get(33100), "");
218         return false;
219       }
220 #endif //HAS_AIRTUNES
221       
222       if (!StartAirPlayServer())
223       {
224         CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(1273), "", g_localizeStrings.Get(33100), "");
225         return false;
226       }      
227     }
228     else
229     {
230       bool ret = true;
231 #ifdef HAS_AIRTUNES
232       if (!StopAirTunesServer(true))
233         ret = false;
234 #endif //HAS_AIRTUNES
235       
236       if (!StopAirPlayServer(true))
237         ret = false;
238
239       if (!ret)
240         return false;
241     }
242   }
243   else if (settingId == "services.airplaypassword" ||
244            settingId == "services.useairplaypassword")
245   {
246     if (!CSettings::Get().GetBool("services.airplay"))
247       return false;
248
249     if (!CAirPlayServer::SetCredentials(CSettings::Get().GetBool("services.useairplaypassword"),
250                                         CSettings::Get().GetString("services.airplaypassword")))
251       return false;
252   }
253   else
254 #endif //HAS_AIRPLAY
255
256 #ifdef HAS_UPNP
257   if (settingId == "services.upnpserver")
258   {
259     if (((CSettingBool*)setting)->GetValue())
260     {
261       if (!StartUPnPServer())
262         return false;
263
264       // always stop and restart the client if necessary
265       StopUPnPClient();
266       StartUPnPClient();
267     }
268     else
269       return StopUPnPServer();
270   }
271   else if (settingId == "services.upnprenderer")
272   {
273     if (((CSettingBool*)setting)->GetValue())
274       return StartUPnPRenderer();
275     else
276       return StopUPnPRenderer();
277   }
278   else if (settingId == "services.upnpcontroller")
279   {
280     // always stop and restart
281     StopUPnPClient();
282     if (((CSettingBool*)setting)->GetValue())
283       return StartUPnPClient();
284   }
285   else
286 #endif // HAS_UPNP
287
288   if (settingId == "services.esenabled")
289   {
290 #ifdef HAS_EVENT_SERVER
291     if (((CSettingBool*)setting)->GetValue())
292     {
293       if (!StartEventServer())
294       {
295         CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33102), "", g_localizeStrings.Get(33100), "");
296         return false;
297       }
298     }
299     else
300       return StopEventServer(true, true);
301 #endif // HAS_EVENT_SERVER
302
303 #ifdef HAS_JSONRPC
304     if (CSettings::Get().GetBool("services.esenabled"))
305     {
306       if (!StartJSONRPCServer())
307       {
308         CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33103), "", g_localizeStrings.Get(33100), "");
309         return false;
310       }
311     }
312     else
313       return StopJSONRPCServer(false);
314 #endif // HAS_JSONRPC
315   }
316   else if (settingId == "services.esport")
317   {
318 #ifdef HAS_EVENT_SERVER
319     // restart eventserver without asking user
320     if (!StopEventServer(true, false))
321       return false;
322
323     if (!StartEventServer())
324     {
325       CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33102), "", g_localizeStrings.Get(33100), "");
326       return false;
327     }
328
329 #if defined(TARGET_DARWIN_OSX)
330     // reconfigure XBMCHelper for port changes
331     XBMCHelper::GetInstance().Configure();
332 #endif // TARGET_DARWIN_OSX
333 #endif // HAS_EVENT_SERVER
334   }
335   else if (settingId == "services.esallinterfaces")
336   {
337 #ifdef HAS_EVENT_SERVER
338     if (CSettings::Get().GetBool("services.esenabled"))
339     {
340       if (!StopEventServer(true, true))
341         return false;
342
343       if (!StartEventServer())
344       {
345         CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33102), "", g_localizeStrings.Get(33100), "");
346         return false;
347       }
348     }
349 #endif // HAS_EVENT_SERVER
350
351 #ifdef HAS_JSONRPC
352     if (CSettings::Get().GetBool("services.esenabled"))
353     {
354       if (!StartJSONRPCServer())
355       {
356         CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33103), "", g_localizeStrings.Get(33100), "");
357         return false;
358       }
359     }
360 #endif // HAS_JSONRPC
361   }
362
363 #ifdef HAS_EVENT_SERVER
364   else if (settingId == "services.esinitialdelay" ||
365            settingId == "services.escontinuousdelay")
366   {
367     if (CSettings::Get().GetBool("services.esenabled"))
368       return RefreshEventServer();
369   }
370 #endif // HAS_EVENT_SERVER
371
372   return true;
373 }
374
375 void CNetworkServices::OnSettingChanged(const CSetting *setting)
376 {
377   if (setting == NULL)
378     return;
379
380   const std::string &settingId = setting->GetId();
381 #ifdef HAS_WEB_SERVER
382   if (settingId == "services.webserverusername" ||
383       settingId == "services.webserverpassword")
384   {
385     m_webserver.SetCredentials(CSettings::Get().GetString("services.webserverusername"),
386                                CSettings::Get().GetString("services.webserverpassword"));
387   }
388   else
389 #endif // HAS_WEB_SERVER
390   if (settingId == "smb.winsserver" ||
391       settingId == "smb.workgroup")
392   {
393     // okey we really don't need to restart, only deinit samba, but that could be damn hard if something is playing
394     // TODO - General way of handling setting changes that require restart
395     if (CGUIDialogYesNo::ShowAndGetInput(14038, 14039, 14040, -1, -1))
396     {
397       CSettings::Get().Save();
398       CApplicationMessenger::Get().RestartApp();
399     }
400   }
401 }
402
403 void CNetworkServices::Start()
404 {
405   StartZeroconf();
406 #ifdef HAS_WEB_SERVER
407   if (CSettings::Get().GetBool("services.webserver") && !StartWebserver())
408     CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(33101), g_localizeStrings.Get(33100));
409 #endif // HAS_WEB_SERVER
410   StartUPnP();
411   if (CSettings::Get().GetBool("services.esenabled") && !StartEventServer())
412     CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(33102), g_localizeStrings.Get(33100));
413   if (CSettings::Get().GetBool("services.esenabled") && !StartJSONRPCServer())
414     CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(33103), g_localizeStrings.Get(33100));
415   
416   // note - airtunesserver has to start before airplay server (ios7 client detection bug)
417   StartAirTunesServer();
418   StartAirPlayServer();
419   StartRss();
420 }
421
422 void CNetworkServices::Stop(bool bWait)
423 {
424   if (bWait)
425   {
426     StopUPnP(bWait);
427     StopZeroconf();
428     StopWebserver();
429     StopRss();
430   }
431
432   StopEventServer(bWait, false);
433   StopJSONRPCServer(bWait);
434   StopAirPlayServer(bWait);
435   StopAirTunesServer(bWait);
436 }
437
438 bool CNetworkServices::StartWebserver()
439 {
440 #ifdef HAS_WEB_SERVER
441   if (!g_application.getNetwork().IsAvailable())
442     return false;
443
444   if (!CSettings::Get().GetBool("services.webserver"))
445     return false;
446
447   int webPort = CSettings::Get().GetInt("services.webserverport");
448   if (!ValidatePort(webPort))
449   {
450     CLog::Log(LOGERROR, "Cannot start Web Server on port %i", webPort);
451     return false;
452   }
453
454   if (IsWebserverRunning())
455     return true;
456
457   CLog::Log(LOGNOTICE, "Webserver: Starting...");
458   if (!m_webserver.Start(webPort, CSettings::Get().GetString("services.webserverusername"), CSettings::Get().GetString("services.webserverpassword")))
459     return false;
460
461 #ifdef HAS_ZEROCONF
462   std::vector<std::pair<std::string, std::string> > txt;
463   // publish web frontend and API services
464 #ifdef HAS_WEB_INTERFACE
465   CZeroconf::GetInstance()->PublishService("servers.webserver", "_http._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt);
466 #endif // HAS_WEB_INTERFACE
467 #ifdef HAS_JSONRPC
468   CZeroconf::GetInstance()->PublishService("servers.jsonrpc-http", "_xbmc-jsonrpc-h._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt);
469 #endif // HAS_JSONRPC
470 #endif // HAS_ZEROCONF
471
472   return true;
473 #endif // HAS_WEB_SERVER
474   return false;
475 }
476
477 bool CNetworkServices::IsWebserverRunning()
478 {
479 #ifdef HAS_WEB_SERVER
480   return m_webserver.IsStarted();
481 #endif // HAS_WEB_SERVER
482   return false;
483 }
484
485 bool CNetworkServices::StopWebserver()
486 {
487 #ifdef HAS_WEB_SERVER
488   if (!IsWebserverRunning())
489     return true;
490
491   CLog::Log(LOGNOTICE, "Webserver: Stopping...");
492   if (!m_webserver.Stop() || m_webserver.IsStarted())
493   {
494     CLog::Log(LOGWARNING, "Webserver: Failed to stop.");
495     return false;
496   }
497   
498   CLog::Log(LOGNOTICE, "Webserver: Stopped...");
499 #ifdef HAS_ZEROCONF
500 #ifdef HAS_WEB_INTERFACE
501   CZeroconf::GetInstance()->RemoveService("servers.webserver");
502 #endif // HAS_WEB_INTERFACE
503 #ifdef HAS_JSONRPC
504   CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-http");
505 #endif // HAS_JSONRPC
506 #endif // HAS_ZEROCONF
507
508   return true;
509 #endif // HAS_WEB_SERVER
510   return false;
511 }
512
513 bool CNetworkServices::StartAirPlayServer()
514 {
515 #ifdef HAS_AIRPLAY
516   if (!g_application.getNetwork().IsAvailable() || !CSettings::Get().GetBool("services.airplay"))
517     return false;
518
519   if (IsAirPlayServerRunning())
520     return true;
521   
522   if (!CAirPlayServer::StartServer(g_advancedSettings.m_airPlayPort, true))
523     return false;
524   
525   if (!CAirPlayServer::SetCredentials(CSettings::Get().GetBool("services.useairplaypassword"),
526                                       CSettings::Get().GetString("services.airplaypassword")))
527     return false;
528   
529 #ifdef HAS_ZEROCONF
530   std::vector<std::pair<std::string, std::string> > txt;
531   CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface();
532   txt.push_back(make_pair("deviceid", iface != NULL ? iface->GetMacAddress() : "FF:FF:FF:FF:FF:F2"));
533   txt.push_back(make_pair("features", "0x77"));
534   txt.push_back(make_pair("model", "Xbmc,1"));
535   txt.push_back(make_pair("srcvers", AIRPLAY_SERVER_VERSION_STR));
536   CZeroconf::GetInstance()->PublishService("servers.airplay", "_airplay._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), g_advancedSettings.m_airPlayPort, txt);
537 #endif // HAS_ZEROCONF
538
539   return true;
540 #endif // HAS_AIRPLAY
541   return false;
542 }
543
544 bool CNetworkServices::IsAirPlayServerRunning()
545 {
546 #ifdef HAS_AIRPLAY
547   return CAirPlayServer::IsRunning();
548 #endif // HAS_AIRPLAY
549   return false;
550 }
551
552 bool CNetworkServices::StopAirPlayServer(bool bWait)
553 {
554 #ifdef HAS_AIRPLAY
555   if (!IsAirPlayServerRunning())
556     return true;
557
558   CAirPlayServer::StopServer(bWait);
559
560 #ifdef HAS_ZEROCONF
561   CZeroconf::GetInstance()->RemoveService("servers.airplay");
562 #endif // HAS_ZEROCONF
563
564   return true;
565 #endif // HAS_AIRPLAY
566   return false;
567 }
568
569 bool CNetworkServices::StartAirTunesServer()
570 {
571 #ifdef HAS_AIRTUNES
572   if (!g_application.getNetwork().IsAvailable() || !CSettings::Get().GetBool("services.airplay"))
573     return false;
574
575   if (IsAirTunesServerRunning())
576     return true;
577
578   if (!CAirTunesServer::StartServer(g_advancedSettings.m_airTunesPort, true,
579                                     CSettings::Get().GetBool("services.useairplaypassword"),
580                                     CSettings::Get().GetString("services.airplaypassword")))
581   {
582     CLog::Log(LOGERROR, "Failed to start AirTunes Server");
583     return false;
584   }
585
586   return true;
587 #endif // HAS_AIRTUNES
588   return false;
589 }
590
591 bool CNetworkServices::IsAirTunesServerRunning()
592 {
593 #ifdef HAS_AIRTUNES
594   return CAirTunesServer::IsRunning();
595 #endif // HAS_AIRTUNES
596   return false;
597 }
598
599 bool CNetworkServices::StopAirTunesServer(bool bWait)
600 {
601 #ifdef HAS_AIRTUNES
602   if (!IsAirTunesServerRunning())
603     return true;
604
605   CAirTunesServer::StopServer(bWait);
606   return true;
607 #endif // HAS_AIRTUNES
608   return false;
609 }
610
611 bool CNetworkServices::StartJSONRPCServer()
612 {
613 #ifdef HAS_JSONRPC
614   if (!CSettings::Get().GetBool("services.esenabled"))
615     return false;
616
617   if (IsJSONRPCServerRunning())
618     return true;
619
620   if (!CTCPServer::StartServer(g_advancedSettings.m_jsonTcpPort, CSettings::Get().GetBool("services.esallinterfaces")))
621     return false;
622
623 #ifdef HAS_ZEROCONF
624   std::vector<std::pair<std::string, std::string> > txt;
625   CZeroconf::GetInstance()->PublishService("servers.jsonrpc-tpc", "_xbmc-jsonrpc._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), g_advancedSettings.m_jsonTcpPort, txt);
626 #endif // HAS_ZEROCONF
627
628   return true;
629 #endif // HAS_JSONRPC
630   return false;
631 }
632
633 bool CNetworkServices::IsJSONRPCServerRunning()
634 {
635 #ifdef HAS_JSONRPC
636   return CTCPServer::IsRunning();
637 #endif // HAS_JSONRPC
638   return false;
639 }
640
641 bool CNetworkServices::StopJSONRPCServer(bool bWait)
642 {
643 #ifdef HAS_JSONRPC
644   if (!IsJSONRPCServerRunning())
645     return true;
646
647   CTCPServer::StopServer(bWait);
648
649 #ifdef HAS_ZEROCONF
650   CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-tcp");
651 #endif // HAS_ZEROCONF
652
653   return true;
654 #endif // HAS_JSONRPC
655   return false;
656 }
657
658 bool CNetworkServices::StartEventServer()
659 {
660 #ifdef HAS_EVENT_SERVER
661   if (!CSettings::Get().GetBool("services.esenabled"))
662     return false;
663
664   if (IsEventServerRunning())
665     return true;
666
667   CEventServer* server = CEventServer::GetInstance();
668   if (!server)
669   {
670     CLog::Log(LOGERROR, "ES: Out of memory");
671     return false;
672   }
673
674   CLog::Log(LOGNOTICE, "ES: Starting event server");
675   server->StartServer();
676
677   return true;
678 #endif // HAS_EVENT_SERVER
679   return false;
680 }
681
682 bool CNetworkServices::IsEventServerRunning()
683 {
684 #ifdef HAS_EVENT_SERVER
685   return CEventServer::GetInstance()->Running();
686 #endif // HAS_EVENT_SERVER
687   return false;
688 }
689
690 bool CNetworkServices::StopEventServer(bool bWait, bool promptuser)
691 {
692 #ifdef HAS_EVENT_SERVER
693   if (!IsEventServerRunning())
694     return true;
695
696   CEventServer* server = CEventServer::GetInstance();
697   if (!server)
698   {
699     CLog::Log(LOGERROR, "ES: Out of memory");
700     return false;
701   }
702
703   if (promptuser)
704   {
705     if (server->GetNumberOfClients() > 0)
706     {
707       bool cancelled = false;
708       if (!CGUIDialogYesNo::ShowAndGetInput(13140, 13141, 13142, 20022,
709                                             -1, -1, cancelled, 10000)
710           || cancelled)
711       {
712         CLog::Log(LOGNOTICE, "ES: Not stopping event server");
713         return false;
714       }
715     }
716     CLog::Log(LOGNOTICE, "ES: Stopping event server with confirmation");
717
718     CEventServer::GetInstance()->StopServer(true);
719   }
720   else
721   {
722     if (!bWait)
723       CLog::Log(LOGNOTICE, "ES: Stopping event server");
724
725     CEventServer::GetInstance()->StopServer(bWait);
726   }
727
728   return true;
729 #endif // HAS_EVENT_SERVER
730   return false;
731 }
732
733 bool CNetworkServices::RefreshEventServer()
734 {
735 #ifdef HAS_EVENT_SERVER
736   if (!CSettings::Get().GetBool("services.esenabled"))
737     return false;
738
739   if (!IsEventServerRunning())
740     return false;
741
742   CEventServer::GetInstance()->RefreshSettings();
743   return true;
744 #endif // HAS_EVENT_SERVER
745   return false;
746 }
747
748 bool CNetworkServices::StartUPnP()
749 {
750   bool ret = false;
751 #ifdef HAS_UPNP
752   ret |= StartUPnPClient();
753   ret |= StartUPnPServer();
754   ret |= StartUPnPRenderer();
755 #endif // HAS_UPNP
756   return ret;
757 }
758
759 bool CNetworkServices::StopUPnP(bool bWait)
760 {
761 #ifdef HAS_UPNP
762   if (!CUPnP::IsInstantiated())
763     return true;
764
765   CLog::Log(LOGNOTICE, "stopping upnp");
766   CUPnP::ReleaseInstance(bWait);
767
768   return true;
769 #endif // HAS_UPNP
770   return false;
771 }
772
773 bool CNetworkServices::StartUPnPClient()
774 {
775 #ifdef HAS_UPNP
776   if (!CSettings::Get().GetBool("services.upnpcontroller") ||
777       !CSettings::Get().GetBool("services.upnpserver"))
778     return false;
779
780   CLog::Log(LOGNOTICE, "starting upnp controller");
781   CUPnP::GetInstance()->StartClient();
782   return IsUPnPClientRunning();
783 #endif // HAS_UPNP
784   return false;
785 }
786
787 bool CNetworkServices::IsUPnPClientRunning()
788 {
789 #ifdef HAS_UPNP
790   return CUPnP::GetInstance()->IsClientStarted();
791 #endif // HAS_UPNP
792   return false;
793 }
794
795 bool CNetworkServices::StopUPnPClient()
796 {
797 #ifdef HAS_UPNP
798   if (!IsUPnPRendererRunning())
799     return true;
800
801   CLog::Log(LOGNOTICE, "stopping upnp client");
802   CUPnP::GetInstance()->StopClient();
803
804   return true;
805 #endif // HAS_UPNP
806   return false;
807 }
808
809 bool CNetworkServices::StartUPnPRenderer()
810 {
811 #ifdef HAS_UPNP
812   if (!CSettings::Get().GetBool("services.upnprenderer"))
813     return false;
814
815   CLog::Log(LOGNOTICE, "starting upnp renderer");
816   return CUPnP::GetInstance()->StartRenderer();
817 #endif // HAS_UPNP
818   return false;
819 }
820
821 bool CNetworkServices::IsUPnPRendererRunning()
822 {
823 #ifdef HAS_UPNP
824   return CUPnP::GetInstance()->IsInstantiated();
825 #endif // HAS_UPNP
826   return false;
827 }
828
829 bool CNetworkServices::StopUPnPRenderer()
830 {
831 #ifdef HAS_UPNP
832   if (!IsUPnPRendererRunning())
833     return true;
834
835   CLog::Log(LOGNOTICE, "stopping upnp renderer");
836   CUPnP::GetInstance()->StopRenderer();
837
838   return true;
839 #endif // HAS_UPNP
840   return false;
841 }
842
843 bool CNetworkServices::StartUPnPServer()
844 {
845 #ifdef HAS_UPNP
846   if (!CSettings::Get().GetBool("services.upnpserver"))
847     return false;
848
849   CLog::Log(LOGNOTICE, "starting upnp server");
850   return CUPnP::GetInstance()->StartServer();
851 #endif // HAS_UPNP
852   return false;
853 }
854
855 bool CNetworkServices::IsUPnPServerRunning()
856 {
857 #ifdef HAS_UPNP
858   return CUPnP::GetInstance()->IsInstantiated();
859 #endif // HAS_UPNP
860   return false;
861 }
862
863 bool CNetworkServices::StopUPnPServer()
864 {
865 #ifdef HAS_UPNP
866   if (!IsUPnPRendererRunning())
867     return true;
868
869   StopUPnPClient();
870
871   CLog::Log(LOGNOTICE, "stopping upnp server");
872   CUPnP::GetInstance()->StopServer();
873
874   return true;
875 #endif // HAS_UPNP
876   return false;
877 }
878   
879 bool CNetworkServices::StartRss()
880 {
881   if (IsRssRunning())
882     return true;
883
884   CRssManager::Get().Start();
885   return true;
886 }
887
888 bool CNetworkServices::IsRssRunning()
889 {
890   return CRssManager::Get().IsActive();
891 }
892
893 bool CNetworkServices::StopRss()
894 {
895   if (!IsRssRunning())
896     return true;
897
898   CRssManager::Get().Stop();
899   return true;
900 }
901
902 bool CNetworkServices::StartZeroconf()
903 {
904 #ifdef HAS_ZEROCONF
905   if (!CSettings::Get().GetBool("services.zeroconf"))
906     return false;
907
908   if (IsZeroconfRunning())
909     return true;
910
911   CLog::Log(LOGNOTICE, "starting zeroconf publishing");
912   return CZeroconf::GetInstance()->Start();
913 #endif // HAS_ZEROCONF
914   return false;
915 }
916
917 bool CNetworkServices::IsZeroconfRunning()
918 {
919 #ifdef HAS_ZEROCONF
920   return CZeroconf::GetInstance()->IsStarted();
921 #endif // HAS_ZEROCONF
922   return false;
923 }
924
925 bool CNetworkServices::StopZeroconf()
926 {
927 #ifdef HAS_ZEROCONF
928   if (!IsZeroconfRunning())
929     return true;
930
931   CLog::Log(LOGNOTICE, "stopping zeroconf publishing");
932   CZeroconf::GetInstance()->Stop();
933
934   return true;
935 #endif // HAS_ZEROCONF
936   return false;
937 }
938
939 bool CNetworkServices::ValidatePort(int port)
940 {
941   if (port <= 0 || port > 65535)
942     return false;
943
944 #ifdef TARGET_LINUX
945   if (!CUtil::CanBindPrivileged() && (port < 1024 || port > 65535))
946     return false;
947 #endif
948
949   return true;
950 }