summaryrefslogtreecommitdiffstats
path: root/xbmc/network/ZeroconfBrowser.h
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/network/ZeroconfBrowser.h')
-rw-r--r--xbmc/network/ZeroconfBrowser.h174
1 files changed, 174 insertions, 0 deletions
diff --git a/xbmc/network/ZeroconfBrowser.h b/xbmc/network/ZeroconfBrowser.h
new file mode 100644
index 0000000..76a4439
--- /dev/null
+++ b/xbmc/network/ZeroconfBrowser.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include <string>
+#include <set>
+#include <vector>
+#include <map>
+
+#ifdef TARGET_WINDOWS
+#undef SetPort // WIN32INCLUDES this is defined as SetPortA in WinSpool.h which is being included _somewhere_
+#endif
+
+//forwards
+class CCriticalSection;
+
+/// this class provides support for zeroconf browsing
+class CZeroconfBrowser
+{
+public:
+ class ZeroconfService
+ {
+ public:
+ typedef std::map<std::string, std::string> tTxtRecordMap;
+
+ ZeroconfService() = default;
+ ZeroconfService(const std::string& fcr_name, const std::string& fcr_type, const std::string& fcr_domain);
+
+ /// easy conversion to string and back (used in czeronfdiretory to store this service)
+ ///@{
+ static std::string toPath(const ZeroconfService& fcr_service);
+ static ZeroconfService fromPath(const std::string& fcr_path); //throws std::runtime_error on failure
+ ///@}
+
+ /// general access methods
+ ///@{
+ void SetName(const std::string& fcr_name);
+ const std::string& GetName() const {return m_name;}
+
+ void SetType(const std::string& fcr_type);
+ const std::string& GetType() const {return m_type;}
+
+ void SetDomain(const std::string& fcr_domain);
+ const std::string& GetDomain() const {return m_domain;}
+ ///@}
+
+ /// access methods needed during resolve
+ ///@{
+ void SetIP(const std::string& fcr_ip);
+ const std::string& GetIP() const {return m_ip;}
+
+ void SetHostname(const std::string& fcr_hostname);
+ const std::string& GetHostname() const {return m_hostname;}
+
+ void SetPort(int f_port);
+ int GetPort() const {return m_port;}
+
+ void SetTxtRecords(const tTxtRecordMap& txt_records);
+ const tTxtRecordMap& GetTxtRecords() const { return m_txtrecords_map;}
+ ///@}
+ private:
+ //3 entries below identify a service
+ std::string m_name;
+ std::string m_type;
+ std::string m_domain;
+
+ //2 entries below store 1 ip:port pair for this service
+ std::string m_ip;
+ int m_port = 0;
+
+ //used for mdns in case dns resolution fails
+ //we store the hostname and resolve with mdns functions again
+ std::string m_hostname;
+
+ //1 entry below stores the txt-record as a key value map for this service
+ tTxtRecordMap m_txtrecords_map;
+ };
+
+ // starts browsing
+ void Start();
+
+ // stops browsing
+ void Stop();
+
+ ///returns the list of found services
+ /// if this is updated, the following message with "zeroconf://" as path is sent:
+ /// CGUIMessage message(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_PATH);
+ std::vector<ZeroconfService> GetFoundServices();
+ ///@}
+
+ // resolves a ZeroconfService to ip + port
+ // @param fcr_service the service to resolve
+ // @param f_timeout timeout in seconds for resolving
+ // the protocol part of CURL is the raw zeroconf service type
+ // added with AddServiceType (== needs further processing! e.g. _smb._tcp -> smb)
+ // @return true if it was successfully resolved (or scheduled), false if resolve
+ // failed (async or not)
+ bool ResolveService(ZeroconfService& fr_service, double f_timeout = 1.0);
+
+ // class methods
+ // access to singleton; singleton gets created on call if not existent
+ // if zeroconf is disabled (!HAS_ZEROCONF), this will return a dummy implementation that
+ // just does nothings, otherwise the platform specific one
+ static CZeroconfBrowser* GetInstance();
+ // release the singleton; (save to call multiple times)
+ static void ReleaseInstance();
+ // returns false if ReleaseInstance() was called before
+ static bool IsInstantiated() { return smp_instance != 0; }
+
+ virtual void ProcessResults() {}
+
+ /// methods for browsing and getting results of it
+ ///@{
+ /// adds a service type for browsing
+ /// @param fcr_service_type the service type as string, e.g. _smb._tcp.
+ /// @return false if it was already there
+ bool AddServiceType(const std::string& fcr_service_type);
+
+ /// remove the specified service from discovery
+ /// @param fcr_service_type the service type as string, e.g. _smb._tcp.
+ /// @return if it was not found
+ bool RemoveServiceType(const std::string& fcr_service_type);
+
+protected:
+ //singleton: we don't want to get instantiated nor copied or deleted from outside
+ CZeroconfBrowser();
+ CZeroconfBrowser(const CZeroconfBrowser&) = delete;
+ CZeroconfBrowser& operator=(const CZeroconfBrowser&) = delete;
+ virtual ~CZeroconfBrowser();
+
+ // pure virtual methods to implement for OS specific implementations
+ virtual bool doAddServiceType(const std::string& fcr_service_type) = 0;
+ virtual bool doRemoveServiceType(const std::string& fcr_service_type) = 0;
+ virtual std::vector<ZeroconfService> doGetFoundServices() = 0;
+ virtual bool doResolveService(ZeroconfService& fr_service, double f_timeout) = 0;
+
+private:
+ struct ServiceInfo
+ {
+ std::string type;
+ };
+
+ //protects data
+ CCriticalSection* mp_crit_sec;
+ typedef std::set<std::string> tServices;
+ tServices m_services;
+ bool m_started = false;
+
+ static CZeroconfBrowser* smp_instance;
+};
+#include <iostream>
+
+//debugging helper
+inline std::ostream& operator<<(std::ostream& o, const CZeroconfBrowser::ZeroconfService& service){
+ o << "(" << service.GetName() << "|" << service.GetType() << "|" << service.GetDomain() << ")";
+ return o;
+}
+
+//inline methods
+inline bool operator<(CZeroconfBrowser::ZeroconfService const& fcr_lhs, CZeroconfBrowser::ZeroconfService const& fcr_rhs)
+{
+ return (fcr_lhs.GetName() + fcr_lhs.GetType() + fcr_lhs.GetDomain() < fcr_rhs.GetName() + fcr_rhs.GetType() + fcr_rhs.GetDomain());
+}
+
+inline bool operator==(CZeroconfBrowser::ZeroconfService const& fcr_lhs, CZeroconfBrowser::ZeroconfService const& fcr_rhs)
+{
+ return (fcr_lhs.GetName() == fcr_rhs.GetName() && fcr_lhs.GetType() == fcr_rhs.GetType() && fcr_lhs.GetDomain() == fcr_rhs.GetDomain() );
+}