--- a/libupnpp/control/service.cxx
+++ b/libupnpp/control/service.cxx
@@ -15,12 +15,19 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string>
+#include <unordered_map>
+#include <functional>
using namespace std;
+using namespace std::placeholders;
+
+#include <upnp/upnp.h>
#include "libupnpp/log.hxx"
+#include "libupnpp/ptmutex.hxx"
#include "libupnpp/upnpplib.hxx"
#include "libupnpp/control/service.hxx"
#include "libupnpp/control/cdirectory.hxx"
+#include "libupnpp/control/avlastchg.hxx"
namespace UPnPClient {
@@ -78,7 +85,7 @@
UpnpGetErrorMessage(ret) << endl);
return ret;
}
- LOGDEB("Result xml: [" << ixmlPrintDocument(response) << "]" << endl);
+ LOGDEB("Service::runAction: Result xml: [" << ixmlPrintDocument(response) << "]" << endl);
if (!decodeSoapBody(args.name.c_str(), response, &data)) {
LOGERR("Service::runAction: Could not decode response: " <<
@@ -88,4 +95,118 @@
return UPNP_E_SUCCESS;
}
-}
+
+static PTMutexInit cblock;
+int Service::srvCB(Upnp_EventType et, void* vevp, void*)
+{
+ PTMutexLocker lock(cblock);
+
+ //LOGDEB("Service:srvCB: " << LibUPnP::evTypeAsString(et) << endl);
+
+ switch (et) {
+ case UPNP_EVENT_RENEWAL_COMPLETE:
+ case UPNP_EVENT_SUBSCRIBE_COMPLETE:
+ case UPNP_EVENT_UNSUBSCRIBE_COMPLETE:
+ case UPNP_EVENT_AUTORENEWAL_FAILED:
+ {
+ const char *ff = (const char *)vevp;
+ LOGDEB("Service:srvCB: subs event: " << ff << endl);
+ break;
+ }
+
+ case UPNP_EVENT_RECEIVED:
+ {
+ struct Upnp_Event *evp = (struct Upnp_Event *)vevp;
+ LOGDEB1("Service:srvCB: var change event: Sid: " <<
+ evp->Sid << " EventKey " << evp->EventKey <<
+ " changed: " << ixmlPrintDocument(evp->ChangedVariables)<< endl);
+
+
+ unordered_map<string, string> props;
+ if (!decodePropertySet(evp->ChangedVariables, props)) {
+ LOGERR("Service::srvCB: could not decode EVENT propertyset" <<endl);
+ return UPNP_E_BAD_RESPONSE;
+ }
+ //for (auto& entry: props) {
+ //LOGDEB(entry.first << " -> " << entry.second << endl;);
+ //}
+ std::unordered_map<std::string, evtCBFunc>::iterator it =
+ o_calls.find(evp->Sid);
+
+ if (it!= o_calls.end()) {
+ (it->second)(props);
+ } else {
+ LOGINF("Service::srvCB: no callback found for " << evp->Sid <<
+ endl);
+ }
+ break;
+ }
+
+ default:
+ // Ignore other events for now
+ LOGDEB("Service:srvCB: unprocessed evt type: [" <<
+ LibUPnP::evTypeAsString(et) << "]" << endl);
+ break;
+ }
+
+ return UPNP_E_SUCCESS;
+}
+
+bool Service::initEvents()
+{
+ LOGDEB("Service::initEvents" << endl);
+
+ PTMutexLocker lock(cblock);
+ static bool eventinit(false);
+ if (eventinit)
+ return true;
+ eventinit = true;
+
+ LibUPnP *lib = LibUPnP::getLibUPnP();
+ if (lib == 0) {
+ LOGERR("Service::initEvents: Can't get lib" << endl);
+ return false;
+ }
+ lib->registerHandler(UPNP_EVENT_RENEWAL_COMPLETE, srvCB, 0);
+ lib->registerHandler(UPNP_EVENT_SUBSCRIBE_COMPLETE, srvCB, 0);
+ lib->registerHandler(UPNP_EVENT_UNSUBSCRIBE_COMPLETE, srvCB, 0);
+ lib->registerHandler(UPNP_EVENT_AUTORENEWAL_FAILED, srvCB, 0);
+ lib->registerHandler(UPNP_EVENT_RECEIVED, srvCB, 0);
+ return true;
+}
+
+//void Service::evtCallback(
+// const std::unordered_map<std::string, std::string>*)
+//{
+// LOGDEB("Service::evtCallback!! service: " << m_serviceType << endl);
+//}
+
+bool Service::subscribe()
+{
+ //LOGDEB("Service::subscribe" << endl);
+ LibUPnP* lib = LibUPnP::getLibUPnP();
+ if (lib == 0) {
+ LOGINF("Service::runAction: no lib" << endl);
+ return UPNP_E_OUTOF_MEMORY;
+ }
+ int timeout = 1800;
+ int ret = UpnpSubscribe(lib->getclh(), m_eventURL.c_str(),
+ &timeout, m_SID);
+ if (ret != UPNP_E_SUCCESS) {
+ LOGERR("Service:subscribe: failed: " <<
+ UpnpGetErrorMessage(ret) << endl);
+ return false;
+ }
+ LOGDEB("Service::subscribe: sid: " << m_SID << endl);
+ return true;
+}
+
+void Service::registerCallback(evtCBFunc c)
+{
+ PTMutexLocker lock(cblock);
+ o_calls[m_SID] = c;
+}
+
+std::unordered_map<std::string, evtCBFunc> Service::o_calls;
+
+}