1 /*
2  *  Copyright (C) 2005-2021 Team Kodi (https://kodi.tv)
3  *
4  *  SPDX-License-Identifier: GPL-2.0-or-later
5  *  See LICENSE.md for more information.
6  */
7 
8 #pragma once
9 
10 #include <atomic>
11 #include <condition_variable>
12 #include <map>
13 #include <mutex>
14 #include <string>
15 #include <vector>
16 
17 extern "C"
18 {
19 #include "libhts/htsmsg.h"
20 }
21 
22 #include "kodi/addon-instance/pvr/General.h"
23 #include "kodi/tools/Thread.h"
24 
25 namespace tvheadend
26 {
27 
28 class HTSPRegister;
29 class HTSPResponse;
30 class IHTSPConnectionListener;
31 
32 namespace utilities
33 {
34 class TCPSocket;
35 }
36 
37 typedef std::map<uint32_t, HTSPResponse*> HTSPResponseList;
38 
39 /*
40  * HTSP Connection
41  */
42 class HTSPConnection : public kodi::tools::CThread
43 {
44 public:
45   HTSPConnection(IHTSPConnectionListener& connListener);
46   ~HTSPConnection() override;
47 
48   void Start();
49   void Stop();
50   void Disconnect();
51 
52   bool SendMessage0(const char* method, htsmsg_t* m);
53   htsmsg_t* SendAndWait0(std::unique_lock<std::recursive_mutex>& lock,
54                          const char* method,
55                          htsmsg_t* m,
56                          int iResponseTimeout = -1);
57   htsmsg_t* SendAndWait(std::unique_lock<std::recursive_mutex>& lock,
58                         const char* method,
59                         htsmsg_t* m,
60                         int iResponseTimeout = -1);
61 
62   int GetProtocol() const;
63 
64   std::string GetWebURL(const char* fmt, ...) const;
65 
66   std::string GetServerName() const;
67   std::string GetServerVersion() const;
68   std::string GetServerString() const;
69 
70   bool HasCapability(const std::string& capability) const;
71 
Mutex()72   std::recursive_mutex& Mutex() { return m_mutex; }
73 
74   void OnSleep();
75   void OnWake();
76 
77 private:
78   // CThread iplementation
79   void Process() override;
80 
ShouldStopProcessing()81   bool ShouldStopProcessing() const { return m_stopProcessing || m_threadStop; }
82 
83   void Register();
84   bool ReadMessage();
85   bool SendHello(std::unique_lock<std::recursive_mutex>& lock);
86   bool SendAuth(std::unique_lock<std::recursive_mutex>& lock,
87                 const std::string& u,
88                 const std::string& p);
89 
90   void SetState(PVR_CONNECTION_STATE state);
91   bool WaitForConnection(std::unique_lock<std::recursive_mutex>& lock);
92 
93   /*
94    * HTSP Connection registration thread
95    */
96   class HTSPRegister : public kodi::tools::CThread
97   {
98   public:
HTSPRegister(HTSPConnection * conn)99     HTSPRegister(HTSPConnection* conn) : m_conn(conn) {}
100 
~HTSPRegister()101     ~HTSPRegister() override { StopThread(); }
102 
103   private:
104     // CThread implementation
Process()105     void Process() override { m_conn->Register(); }
106 
107     HTSPConnection* m_conn;
108   };
109 
110   IHTSPConnectionListener& m_connListener;
111   tvheadend::utilities::TCPSocket* m_socket = nullptr;
112   mutable std::recursive_mutex m_mutex;
113   HTSPRegister* m_regThread;
114   std::condition_variable_any m_regCond;
115   bool m_ready;
116   uint32_t m_seq;
117   std::string m_serverName;
118   std::string m_serverVersion;
119   int m_htspVersion;
120   std::string m_webRoot;
121   void* m_challenge;
122   int m_challengeLen;
123 
124   HTSPResponseList m_messages;
125   std::vector<std::string> m_capabilities;
126 
127   bool m_suspended;
128   PVR_CONNECTION_STATE m_state;
129 
130   std::atomic<bool> m_stopProcessing = false;
131 };
132 
133 } // namespace tvheadend
134