00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00012
00013 #ifndef EVENTING_H_
00014 #define EVENTING_H_
00015
00016 #include <QUrl>
00017 #include <QUuid>
00018 #include <QMap>
00019
00020 #include "upnpserviceimpl.h"
00021 #include "upnputil.h"
00022 #include "httpserver.h"
00023
00024 class QTextStream;
00025
00027
00029
00030 class UPNP_PUBLIC SubscriberInfo
00031 {
00032 public:
00033 SubscriberInfo()
00034 : nKey( 0 ), nDuration( 0 )
00035 {
00036 memset( &ttExpires, 0, sizeof( ttExpires ) );
00037 memset( &ttLastNotified, 0, sizeof( ttLastNotified ) );
00038 sUUID = QUuid::createUuid().toString();
00039 sUUID = sUUID.mid( 1, sUUID.length() - 2);
00040 }
00041
00042 SubscriberInfo( const QString &url, unsigned long duration )
00043 : nKey( 0 ), nDuration( duration )
00044 {
00045 memset( &ttExpires, 0, sizeof( ttExpires ) );
00046 memset( &ttLastNotified, 0, sizeof( ttLastNotified ) );
00047 sUUID = QUuid::createUuid().toString();
00048 sUUID = sUUID.mid( 1, sUUID.length() - 2);
00049 qURL = url;
00050
00051 SetExpireTime( nDuration );
00052 }
00053
00054 unsigned long IncrementKey()
00055 {
00056
00057 if ((++nKey) == 0)
00058 nKey = 1;
00059
00060 return nKey;
00061 }
00062
00063 TaskTime ttExpires;
00064 TaskTime ttLastNotified;
00065
00066 QString sUUID;
00067 QUrl qURL;
00068 unsigned short nKey;
00069 unsigned long nDuration;
00070
00071 protected:
00072
00073 void SetExpireTime( unsigned long nSecs )
00074 {
00075 TaskTime tt;
00076 gettimeofday( (&tt), NULL );
00077
00078 AddMicroSecToTaskTime( tt, (nSecs * 1000000) );
00079
00080 ttExpires = tt;
00081 }
00082
00083
00084 };
00085
00087
00088 typedef QMap<QString,SubscriberInfo*> Subscribers;
00089
00091
00093
00094 class UPNP_PUBLIC StateVariableBase
00095 {
00096 public:
00097
00098 bool m_bNotify;
00099 QString m_sName;
00100 TaskTime m_ttLastChanged;
00101
00102 public:
00103
00104 explicit StateVariableBase( const QString &sName, bool bNotify = false )
00105 {
00106 m_bNotify = bNotify;
00107 m_sName = sName;
00108 gettimeofday( (&m_ttLastChanged), NULL );
00109 }
00110 virtual ~StateVariableBase() {};
00111
00112 virtual QString ToString() = 0;
00113 };
00114
00116
00117 template< class T >
00118 class UPNP_PUBLIC StateVariable : public StateVariableBase
00119 {
00120 private:
00121
00122 T m_value;
00123
00124 public:
00125
00126
00127
00128 StateVariable( const QString &sName, bool bNotify = false ) : StateVariableBase( sName, bNotify ), m_value( T( ) )
00129 {
00130 }
00131
00132
00133
00134 StateVariable( const QString &sName, T value, bool bNotify = false ) : StateVariableBase( sName, bNotify ), m_value(value)
00135 {
00136 }
00137
00138
00139
00140 virtual QString ToString()
00141 {
00142 return QString( "%1" ).arg( m_value );
00143 }
00144
00145
00146
00147 T GetValue()
00148 {
00149 return m_value;
00150 }
00151
00152
00153
00154 void SetValue( T value )
00155 {
00156 if ( m_value != value )
00157 {
00158 m_value = value;
00159 gettimeofday( (&m_ttLastChanged), NULL );
00160 }
00161 }
00162 };
00163
00165
00166 template<typename T>
00167 inline T state_var_init(const T*) { return (T)(0); }
00168 template<>
00169 inline QString state_var_init(const QString*) { return QString(); }
00170
00171 class UPNP_PUBLIC StateVariables
00172 {
00173 protected:
00174
00175 virtual void Notify() = 0;
00176 typedef QMap<QString, StateVariableBase*> SVMap;
00177 SVMap m_map;
00178 public:
00179
00180
00181
00182 StateVariables() { }
00183 virtual ~StateVariables()
00184 {
00185 SVMap::iterator it = m_map.begin();
00186 for (; it != m_map.end(); ++it)
00187 delete *it;
00188 m_map.clear();
00189 }
00190
00191
00192
00193 void AddVariable( StateVariableBase *pBase )
00194 {
00195 if (pBase != NULL)
00196 m_map.insert(pBase->m_sName, pBase);
00197 }
00198
00199
00200 template < class T >
00201 bool SetValue( const QString &sName, T value )
00202 {
00203 SVMap::iterator it = m_map.find(sName);
00204 if (it == m_map.end())
00205 return false;
00206
00207 StateVariable< T > *pVariable =
00208 dynamic_cast< StateVariable< T > *>( *it );
00209
00210 if (pVariable == NULL)
00211 return false;
00212
00213 if ( pVariable->GetValue() != value)
00214 {
00215 pVariable->SetValue( value );
00216
00217 if (pVariable->m_bNotify)
00218 Notify();
00219 }
00220
00221 return true;
00222 }
00223
00224
00225
00226 template < class T >
00227 T GetValue( const QString &sName )
00228 {
00229 T *dummy = NULL;
00230 SVMap::iterator it = m_map.find(sName);
00231 if (it == m_map.end())
00232 return state_var_init(dummy);
00233
00234 StateVariable< T > *pVariable =
00235 dynamic_cast< StateVariable< T > *>( *it );
00236
00237 if (pVariable != NULL)
00238 return pVariable->GetValue();
00239
00240 return state_var_init(dummy);
00241 }
00242
00243 uint BuildNotifyBody(QTextStream &ts, TaskTime ttLastNotified) const;
00244 };
00245
00248
00249
00250
00253
00254 class UPNP_PUBLIC Eventing : public HttpServerExtension,
00255 public StateVariables,
00256 public IPostProcess,
00257 public UPnpServiceImpl
00258 {
00259
00260 protected:
00261
00262 QMutex m_mutex;
00263
00264 QString m_sEventMethodName;
00265 Subscribers m_Subscribers;
00266
00267 int m_nSubscriptionDuration;
00268
00269 short m_nHoldCount;
00270
00271 SubscriberInfo *m_pInitializeSubscriber;
00272
00273 protected:
00274
00275 virtual void Notify ( );
00276 void NotifySubscriber ( SubscriberInfo *pInfo );
00277 void HandleSubscribe ( HTTPRequest *pRequest );
00278 void HandleUnsubscribe( HTTPRequest *pRequest );
00279
00280
00281
00282 virtual QString GetServiceEventURL () { return m_sEventMethodName; }
00283
00284 public:
00285 Eventing ( const QString &sExtensionName,
00286 const QString &sEventMethodName,
00287 const QString sSharePath );
00288 virtual ~Eventing ( );
00289
00290 virtual QStringList GetBasePaths();
00291
00292 virtual bool ProcessRequest( HTTPRequest *pRequest );
00293
00294 short HoldEvents ( );
00295 short ReleaseEvents ( );
00296
00297 void ExecutePostProcess( );
00298
00299
00300 };
00301
00302 #endif