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
00111 virtual QString ToString() = 0;
00112 };
00113
00115
00116 template< class T >
00117 class UPNP_PUBLIC StateVariable : public StateVariableBase
00118 {
00119 private:
00120
00121 T m_value;
00122
00123 public:
00124
00125
00126
00127 StateVariable( const QString &sName, bool bNotify = false ) : StateVariableBase( sName, bNotify ), m_value( T( ) )
00128 {
00129 }
00130
00131
00132
00133 StateVariable( const QString &sName, T value, bool bNotify = false ) : StateVariableBase( sName, bNotify ), m_value(value)
00134 {
00135 }
00136
00137
00138
00139 virtual QString ToString()
00140 {
00141 return QString( "%1" ).arg( m_value );
00142 }
00143
00144
00145
00146 T GetValue()
00147 {
00148 return m_value;
00149 }
00150
00151
00152
00153 void SetValue( T value )
00154 {
00155 if ( m_value != value )
00156 {
00157 m_value = value;
00158 gettimeofday( (&m_ttLastChanged), NULL );
00159 }
00160 }
00161 };
00162
00164
00165 template<typename T>
00166 inline T state_var_init(const T*) { return (T)(0); }
00167 template<>
00168 inline QString state_var_init(const QString*) { return QString(); }
00169
00170 class UPNP_PUBLIC StateVariables
00171 {
00172 protected:
00173
00174 virtual void Notify() = 0;
00175 typedef QMap<QString, StateVariableBase*> SVMap;
00176 SVMap m_map;
00177 public:
00178
00179
00180
00181 StateVariables() { }
00182 virtual ~StateVariables()
00183 {
00184 SVMap::iterator it = m_map.begin();
00185 for (; it != m_map.end(); ++it)
00186 delete *it;
00187 m_map.clear();
00188 }
00189
00190
00191
00192 void AddVariable( StateVariableBase *pBase )
00193 {
00194 if (pBase != NULL)
00195 m_map.insert(pBase->m_sName, pBase);
00196 }
00197
00198
00199 template < class T >
00200 bool SetValue( const QString &sName, T value )
00201 {
00202 SVMap::iterator it = m_map.find(sName);
00203 if (it == m_map.end())
00204 return false;
00205
00206 StateVariable< T > *pVariable =
00207 dynamic_cast< StateVariable< T > *>( *it );
00208
00209 if (pVariable == NULL)
00210 return false;
00211
00212 if ( pVariable->GetValue() != value)
00213 {
00214 pVariable->SetValue( value );
00215
00216 if (pVariable->m_bNotify)
00217 Notify();
00218 }
00219
00220 return true;
00221 }
00222
00223
00224
00225 template < class T >
00226 T GetValue( const QString &sName )
00227 {
00228 T *dummy = NULL;
00229 SVMap::iterator it = m_map.find(sName);
00230 if (it == m_map.end())
00231 return state_var_init(dummy);
00232
00233 StateVariable< T > *pVariable =
00234 dynamic_cast< StateVariable< T > *>( *it );
00235
00236 if (pVariable != NULL)
00237 return pVariable->GetValue();
00238
00239 return state_var_init(dummy);
00240 }
00241
00242 uint BuildNotifyBody(QTextStream &ts, TaskTime ttLastNotified) const;
00243 };
00244
00247
00248
00249
00252
00253 class UPNP_PUBLIC Eventing : public HttpServerExtension,
00254 public StateVariables,
00255 public IPostProcess,
00256 public UPnpServiceImpl
00257 {
00258
00259 protected:
00260
00261 QMutex m_mutex;
00262
00263 QString m_sEventMethodName;
00264 Subscribers m_Subscribers;
00265
00266 int m_nSubscriptionDuration;
00267
00268 short m_nHoldCount;
00269
00270 SubscriberInfo *m_pInitializeSubscriber;
00271
00272 protected:
00273
00274 virtual void Notify ( );
00275 void NotifySubscriber ( SubscriberInfo *pInfo );
00276 void HandleSubscribe ( HTTPRequest *pRequest );
00277 void HandleUnsubscribe( HTTPRequest *pRequest );
00278
00279
00280
00281 virtual QString GetServiceEventURL () { return m_sEventMethodName; }
00282
00283 public:
00284 Eventing ( const QString &sExtensionName,
00285 const QString &sEventMethodName,
00286 const QString sSharePath );
00287 virtual ~Eventing ( );
00288
00289 virtual QStringList GetBasePaths();
00290
00291 virtual bool ProcessRequest( HTTPRequest *pRequest );
00292
00293 short HoldEvents ( );
00294 short ReleaseEvents ( );
00295
00296 void ExecutePostProcess( );
00297
00298
00299 };
00300
00301 #endif