|
a/libupnpp/control/service.cxx |
|
b/libupnpp/control/service.cxx |
|
... |
|
... |
13 |
* along with this program; if not, write to the
|
13 |
* along with this program; if not, write to the
|
14 |
* Free Software Foundation, Inc.,
|
14 |
* Free Software Foundation, Inc.,
|
15 |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
15 |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16 |
*/
|
16 |
*/
|
17 |
#include <string>
|
17 |
#include <string>
|
|
|
18 |
#include <unordered_map>
|
|
|
19 |
#include <functional>
|
18 |
using namespace std;
|
20 |
using namespace std;
|
|
|
21 |
using namespace std::placeholders;
|
|
|
22 |
|
|
|
23 |
#include <upnp/upnp.h>
|
19 |
|
24 |
|
20 |
#include "libupnpp/log.hxx"
|
25 |
#include "libupnpp/log.hxx"
|
|
|
26 |
#include "libupnpp/ptmutex.hxx"
|
21 |
#include "libupnpp/upnpplib.hxx"
|
27 |
#include "libupnpp/upnpplib.hxx"
|
22 |
#include "libupnpp/control/service.hxx"
|
28 |
#include "libupnpp/control/service.hxx"
|
23 |
#include "libupnpp/control/cdirectory.hxx"
|
29 |
#include "libupnpp/control/cdirectory.hxx"
|
|
|
30 |
#include "libupnpp/control/avlastchg.hxx"
|
24 |
|
31 |
|
25 |
namespace UPnPClient {
|
32 |
namespace UPnPClient {
|
26 |
|
33 |
|
27 |
Service *service_factory(const string& servicetype,
|
34 |
Service *service_factory(const string& servicetype,
|
28 |
const UPnPDeviceDesc& device,
|
35 |
const UPnPDeviceDesc& device,
|
|
... |
|
... |
76 |
if (ret != UPNP_E_SUCCESS) {
|
83 |
if (ret != UPNP_E_SUCCESS) {
|
77 |
LOGINF("Service::runAction: UpnpSendAction failed: " <<
|
84 |
LOGINF("Service::runAction: UpnpSendAction failed: " <<
|
78 |
UpnpGetErrorMessage(ret) << endl);
|
85 |
UpnpGetErrorMessage(ret) << endl);
|
79 |
return ret;
|
86 |
return ret;
|
80 |
}
|
87 |
}
|
81 |
LOGDEB("Result xml: [" << ixmlPrintDocument(response) << "]" << endl);
|
88 |
LOGDEB("Service::runAction: Result xml: [" << ixmlPrintDocument(response) << "]" << endl);
|
82 |
|
89 |
|
83 |
if (!decodeSoapBody(args.name.c_str(), response, &data)) {
|
90 |
if (!decodeSoapBody(args.name.c_str(), response, &data)) {
|
84 |
LOGERR("Service::runAction: Could not decode response: " <<
|
91 |
LOGERR("Service::runAction: Could not decode response: " <<
|
85 |
ixmlPrintDocument(response) << endl);
|
92 |
ixmlPrintDocument(response) << endl);
|
86 |
return UPNP_E_BAD_RESPONSE;
|
93 |
return UPNP_E_BAD_RESPONSE;
|
87 |
}
|
94 |
}
|
88 |
return UPNP_E_SUCCESS;
|
95 |
return UPNP_E_SUCCESS;
|
89 |
}
|
96 |
}
|
90 |
|
97 |
|
|
|
98 |
|
|
|
99 |
static PTMutexInit cblock;
|
|
|
100 |
int Service::srvCB(Upnp_EventType et, void* vevp, void*)
|
|
|
101 |
{
|
|
|
102 |
PTMutexLocker lock(cblock);
|
|
|
103 |
|
|
|
104 |
//LOGDEB("Service:srvCB: " << LibUPnP::evTypeAsString(et) << endl);
|
|
|
105 |
|
|
|
106 |
switch (et) {
|
|
|
107 |
case UPNP_EVENT_RENEWAL_COMPLETE:
|
|
|
108 |
case UPNP_EVENT_SUBSCRIBE_COMPLETE:
|
|
|
109 |
case UPNP_EVENT_UNSUBSCRIBE_COMPLETE:
|
|
|
110 |
case UPNP_EVENT_AUTORENEWAL_FAILED:
|
|
|
111 |
{
|
|
|
112 |
const char *ff = (const char *)vevp;
|
|
|
113 |
LOGDEB("Service:srvCB: subs event: " << ff << endl);
|
|
|
114 |
break;
|
|
|
115 |
}
|
|
|
116 |
|
|
|
117 |
case UPNP_EVENT_RECEIVED:
|
|
|
118 |
{
|
|
|
119 |
struct Upnp_Event *evp = (struct Upnp_Event *)vevp;
|
|
|
120 |
LOGDEB1("Service:srvCB: var change event: Sid: " <<
|
|
|
121 |
evp->Sid << " EventKey " << evp->EventKey <<
|
|
|
122 |
" changed: " << ixmlPrintDocument(evp->ChangedVariables)<< endl);
|
|
|
123 |
|
|
|
124 |
|
|
|
125 |
unordered_map<string, string> props;
|
|
|
126 |
if (!decodePropertySet(evp->ChangedVariables, props)) {
|
|
|
127 |
LOGERR("Service::srvCB: could not decode EVENT propertyset" <<endl);
|
|
|
128 |
return UPNP_E_BAD_RESPONSE;
|
|
|
129 |
}
|
|
|
130 |
//for (auto& entry: props) {
|
|
|
131 |
//LOGDEB(entry.first << " -> " << entry.second << endl;);
|
|
|
132 |
//}
|
|
|
133 |
std::unordered_map<std::string, evtCBFunc>::iterator it =
|
|
|
134 |
o_calls.find(evp->Sid);
|
|
|
135 |
|
|
|
136 |
if (it!= o_calls.end()) {
|
|
|
137 |
(it->second)(props);
|
|
|
138 |
} else {
|
|
|
139 |
LOGINF("Service::srvCB: no callback found for " << evp->Sid <<
|
|
|
140 |
endl);
|
|
|
141 |
}
|
|
|
142 |
break;
|
|
|
143 |
}
|
|
|
144 |
|
|
|
145 |
default:
|
|
|
146 |
// Ignore other events for now
|
|
|
147 |
LOGDEB("Service:srvCB: unprocessed evt type: [" <<
|
|
|
148 |
LibUPnP::evTypeAsString(et) << "]" << endl);
|
|
|
149 |
break;
|
|
|
150 |
}
|
|
|
151 |
|
|
|
152 |
return UPNP_E_SUCCESS;
|
91 |
}
|
153 |
}
|
|
|
154 |
|
|
|
155 |
bool Service::initEvents()
|
|
|
156 |
{
|
|
|
157 |
LOGDEB("Service::initEvents" << endl);
|
|
|
158 |
|
|
|
159 |
PTMutexLocker lock(cblock);
|
|
|
160 |
static bool eventinit(false);
|
|
|
161 |
if (eventinit)
|
|
|
162 |
return true;
|
|
|
163 |
eventinit = true;
|
|
|
164 |
|
|
|
165 |
LibUPnP *lib = LibUPnP::getLibUPnP();
|
|
|
166 |
if (lib == 0) {
|
|
|
167 |
LOGERR("Service::initEvents: Can't get lib" << endl);
|
|
|
168 |
return false;
|
|
|
169 |
}
|
|
|
170 |
lib->registerHandler(UPNP_EVENT_RENEWAL_COMPLETE, srvCB, 0);
|
|
|
171 |
lib->registerHandler(UPNP_EVENT_SUBSCRIBE_COMPLETE, srvCB, 0);
|
|
|
172 |
lib->registerHandler(UPNP_EVENT_UNSUBSCRIBE_COMPLETE, srvCB, 0);
|
|
|
173 |
lib->registerHandler(UPNP_EVENT_AUTORENEWAL_FAILED, srvCB, 0);
|
|
|
174 |
lib->registerHandler(UPNP_EVENT_RECEIVED, srvCB, 0);
|
|
|
175 |
return true;
|
|
|
176 |
}
|
|
|
177 |
|
|
|
178 |
//void Service::evtCallback(
|
|
|
179 |
// const std::unordered_map<std::string, std::string>*)
|
|
|
180 |
//{
|
|
|
181 |
// LOGDEB("Service::evtCallback!! service: " << m_serviceType << endl);
|
|
|
182 |
//}
|
|
|
183 |
|
|
|
184 |
bool Service::subscribe()
|
|
|
185 |
{
|
|
|
186 |
//LOGDEB("Service::subscribe" << endl);
|
|
|
187 |
LibUPnP* lib = LibUPnP::getLibUPnP();
|
|
|
188 |
if (lib == 0) {
|
|
|
189 |
LOGINF("Service::runAction: no lib" << endl);
|
|
|
190 |
return UPNP_E_OUTOF_MEMORY;
|
|
|
191 |
}
|
|
|
192 |
int timeout = 1800;
|
|
|
193 |
int ret = UpnpSubscribe(lib->getclh(), m_eventURL.c_str(),
|
|
|
194 |
&timeout, m_SID);
|
|
|
195 |
if (ret != UPNP_E_SUCCESS) {
|
|
|
196 |
LOGERR("Service:subscribe: failed: " <<
|
|
|
197 |
UpnpGetErrorMessage(ret) << endl);
|
|
|
198 |
return false;
|
|
|
199 |
}
|
|
|
200 |
LOGDEB("Service::subscribe: sid: " << m_SID << endl);
|
|
|
201 |
return true;
|
|
|
202 |
}
|
|
|
203 |
|
|
|
204 |
void Service::registerCallback(evtCBFunc c)
|
|
|
205 |
{
|
|
|
206 |
PTMutexLocker lock(cblock);
|
|
|
207 |
o_calls[m_SID] = c;
|
|
|
208 |
}
|
|
|
209 |
|
|
|
210 |
std::unordered_map<std::string, evtCBFunc> Service::o_calls;
|
|
|
211 |
|
|
|
212 |
}
|