MythTV  master
eventing.h
Go to the documentation of this file.
1 // Program Name: Eventing.h
3 // Created : Dec. 22, 2006
4 //
5 // Purpose : uPnp Eventing Base Class Definition
6 //
7 // Copyright (c) 2006 David Blain <dblain@mythtv.org>
8 //
9 // Licensed under the GPL v2 or later, see LICENSE for details
10 //
12 
13 #ifndef EVENTING_H_
14 #define EVENTING_H_
15 
16 #include <QUrl>
17 #include <QUuid>
18 #include <QMap>
19 
20 #include "upnpserviceimpl.h"
21 #include "upnputil.h"
22 #include "httpserver.h"
23 
24 class QTextStream;
25 
27 //
29 
31 {
32  public:
34  {
35  m_ttExpires = 0us;
36  m_ttLastNotified = 0us;
37  m_sUUID = QUuid::createUuid().toString();
38  m_sUUID = m_sUUID.mid( 1, m_sUUID.length() - 2);
39  }
40 
41  SubscriberInfo( const QString &url, std::chrono::seconds duration )
42  : m_nDuration( duration )
43  {
44  m_ttExpires = 0us;
45  m_ttLastNotified = 0us;
46  m_sUUID = QUuid::createUuid().toString();
47  m_sUUID = m_sUUID.mid( 1, m_sUUID.length() - 2);
48  m_qURL = url;
49 
50  SetExpireTime( m_nDuration );
51  }
52 
53  unsigned long IncrementKey()
54  {
55  // When key wraps around to zero again... must make it a 1. (upnp spec)
56  if ((++m_nKey) == 0)
57  m_nKey = 1;
58 
59  return m_nKey;
60  }
61 
62  TaskTime m_ttExpires {};
63  TaskTime m_ttLastNotified {};
64 
65  QString m_sUUID;
66  QUrl m_qURL;
67  unsigned short m_nKey {0};
68  std::chrono::seconds m_nDuration {0s};
69 
70  protected:
71 
72  void SetExpireTime( std::chrono::seconds secs )
73  {
74  m_ttExpires = nowAsDuration<std::chrono::microseconds>() + secs;
75  }
76 
77 
78 };
79 
81 
82 using Subscribers = QMap<QString,SubscriberInfo*>;
83 
85 //
87 
89 {
90  public:
91 
92  bool m_bNotify;
93  QString m_sName;
94  TaskTime m_ttLastChanged {};
95 
96  public:
97 
98  explicit StateVariableBase( const QString &sName, bool bNotify = false )
99  {
100  m_bNotify = bNotify;
101  m_sName = sName;
102  m_ttLastChanged = nowAsDuration<std::chrono::microseconds>();
103  }
104  virtual ~StateVariableBase() = default;
105 
106  virtual QString ToString() = 0;
107 };
108 
110 
111 template< class T >
113 {
114  private:
115 
117 
118  public:
119 
120  // ------------------------------------------------------------------
121 
122  explicit StateVariable( const QString &sName, bool bNotify = false ) : StateVariableBase( sName, bNotify ), m_value( T( ) )
123  {
124  }
125 
126  // ------------------------------------------------------------------
127 
128  StateVariable( const QString &sName, T value, bool bNotify = false ) : StateVariableBase( sName, bNotify ), m_value(value)
129  {
130  }
131 
132  // ------------------------------------------------------------------
133 
134  QString ToString() override // StateVariableBase
135  {
136  return QString( "%1" ).arg( m_value );
137  }
138 
139  // ------------------------------------------------------------------
140 
142  {
143  return m_value;
144  }
145 
146  // ------------------------------------------------------------------
147 
148  void SetValue( T value )
149  {
150  if ( m_value != value )
151  {
152  m_value = value;
153  m_ttLastChanged = nowAsDuration<std::chrono::microseconds>();
154  }
155  }
156 };
157 
159 
160 template<typename T>
161 inline T state_var_init(const T */*unused*/) { return (T)(0); }
162 template<>
163 inline QString state_var_init(const QString */*unused*/) { return {}; }
164 
166 {
167  protected:
168 
169  virtual void Notify() = 0;
170  using SVMap = QMap<QString, StateVariableBase*>;
172  public:
173 
174  // ------------------------------------------------------------------
175 
176  StateVariables() = default;
177  virtual ~StateVariables()
178  {
179  for (const auto *it : std::as_const(m_map))
180  delete it;
181  m_map.clear();
182  }
183 
184  // ------------------------------------------------------------------
185 
187  {
188  if (pBase != nullptr)
189  m_map.insert(pBase->m_sName, pBase);
190  }
191 
192  // ------------------------------------------------------------------
193  template < class T >
194  bool SetValue( const QString &sName, T value )
195  {
196  SVMap::iterator it = m_map.find(sName);
197  if (it == m_map.end())
198  return false;
199 
200  auto *pVariable = dynamic_cast< StateVariable< T > *>( *it );
201 
202  if (pVariable == nullptr)
203  return false; // It's not the expected type.
204 
205  if ( pVariable->GetValue() != value)
206  {
207  pVariable->SetValue( value );
208 
209  if (pVariable->m_bNotify)
210  Notify();
211  }
212 
213  return true;
214  }
215 
216  // ------------------------------------------------------------------
217 
218  template < class T >
219  T GetValue( const QString &sName )
220  {
221  T *dummy = nullptr;
222  SVMap::iterator it = m_map.find(sName);
223  if (it == m_map.end())
224  return state_var_init(dummy);
225 
226  auto *pVariable = dynamic_cast< StateVariable< T > *>( *it );
227 
228  if (pVariable != nullptr)
229  return pVariable->GetValue();
230 
231  return state_var_init(dummy);
232  }
233 
234  uint BuildNotifyBody(QTextStream &ts, TaskTime ttLastNotified) const;
235 };
236 
239 //
240 // Eventing Class Definition
241 //
244 
246  public StateVariables,
247  public IPostProcess,
248  public UPnpServiceImpl
249 {
250 
251  protected:
252 
253  QMutex m_mutex;
254 
257 
258  std::chrono::seconds m_nSubscriptionDuration {30min};
259 
260  short m_nHoldCount {0};
261 
262  SubscriberInfo *m_pInitializeSubscriber {nullptr};
263 
264  protected:
265 
266  void Notify ( ) override; // StateVariables
267  void NotifySubscriber ( SubscriberInfo *pInfo );
268  void HandleSubscribe ( HTTPRequest *pRequest );
269  void HandleUnsubscribe( HTTPRequest *pRequest );
270 
271  // Implement UPnpServiceImpl methods that we can
272 
273  QString GetServiceEventURL() override // UPnpServiceImpl
274  { return m_sEventMethodName; }
275 
276  public:
277  Eventing ( const QString &sExtensionName,
278  QString sEventMethodName,
279  const QString &sSharePath );
280  ~Eventing ( ) override;
281 
282  QStringList GetBasePaths() override; // HttpServerExtension
283 
284  bool ProcessRequest( HTTPRequest *pRequest ) override; // HttpServerExtension
285 
286  short HoldEvents ( );
287  short ReleaseEvents ( );
288 
289  void ExecutePostProcess( ) override; // IPostProcess
290 
291 
292 };
293 
294 #endif
SubscriberInfo::SubscriberInfo
SubscriberInfo()
Definition: eventing.h:33
StateVariables::Notify
virtual void Notify()=0
state_var_init
T state_var_init(const T *)
Definition: eventing.h:161
HTTPRequest
Definition: httprequest.h:109
Eventing::m_subscribers
Subscribers m_subscribers
Definition: eventing.h:256
SubscriberInfo::SetExpireTime
void SetExpireTime(std::chrono::seconds secs)
Definition: eventing.h:72
TaskTime
std::chrono::microseconds TaskTime
Definition: upnputil.h:31
Eventing::m_sEventMethodName
QString m_sEventMethodName
Definition: eventing.h:255
StateVariables::m_map
SVMap m_map
Definition: eventing.h:171
StateVariable::GetValue
T GetValue()
Definition: eventing.h:141
Eventing
Definition: eventing.h:245
StateVariable
Definition: eventing.h:112
StateVariable::ToString
QString ToString() override
Definition: eventing.h:134
StateVariableBase::m_bNotify
bool m_bNotify
Definition: eventing.h:92
StateVariable::StateVariable
StateVariable(const QString &sName, bool bNotify=false)
Definition: eventing.h:122
SubscriberInfo
Definition: eventing.h:30
Subscribers
QMap< QString, SubscriberInfo * > Subscribers
Definition: eventing.h:82
SubscriberInfo::m_sUUID
QString m_sUUID
Definition: eventing.h:65
IPostProcess::ExecutePostProcess
virtual void ExecutePostProcess()=0
StateVariables::SVMap
QMap< QString, StateVariableBase * > SVMap
Definition: eventing.h:170
SubscriberInfo::IncrementKey
unsigned long IncrementKey()
Definition: eventing.h:53
StateVariables::SetValue
bool SetValue(const QString &sName, T value)
Definition: eventing.h:194
uint
unsigned int uint
Definition: compat.h:81
SubscriberInfo::m_qURL
QUrl m_qURL
Definition: eventing.h:66
HttpServerExtension::ProcessRequest
virtual bool ProcessRequest(HTTPRequest *pRequest)=0
IPostProcess
Definition: httprequest.h:98
StateVariableBase::StateVariableBase
StateVariableBase(const QString &sName, bool bNotify=false)
Definition: eventing.h:98
Eventing::m_mutex
QMutex m_mutex
Definition: eventing.h:253
SubscriberInfo::SubscriberInfo
SubscriberInfo(const QString &url, std::chrono::seconds duration)
Definition: eventing.h:41
Eventing::GetServiceEventURL
QString GetServiceEventURL() override
Provides the URL of the event portion of the service.
Definition: eventing.h:273
HttpServerExtension::GetBasePaths
virtual QStringList GetBasePaths()=0
StateVariable::m_value
T m_value
Definition: eventing.h:116
StateVariable::SetValue
void SetValue(T value)
Definition: eventing.h:148
StateVariables::AddVariable
void AddVariable(StateVariableBase *pBase)
Definition: eventing.h:186
UPNP_PUBLIC
#define UPNP_PUBLIC
Definition: upnpexp.h:9
StateVariables::~StateVariables
virtual ~StateVariables()
Definition: eventing.h:177
httpserver.h
upnpserviceimpl.h
HttpServerExtension
Definition: httpserver.h:71
upnputil.h
StateVariables
Definition: eventing.h:165
StateVariables::GetValue
T GetValue(const QString &sName)
Definition: eventing.h:219
StateVariableBase::m_sName
QString m_sName
Definition: eventing.h:93
UPnpServiceImpl
Base class for services we offer to other UPnP devices.
Definition: upnpserviceimpl.h:29
StateVariable::StateVariable
StateVariable(const QString &sName, T value, bool bNotify=false)
Definition: eventing.h:128
StateVariableBase
Definition: eventing.h:88