18 #define SUBSCRIPTION_TIME 1800
20 #define MAX_WAIT 30000
22 #define LOC QString("UPnPSub: ")
36 m_subscriptionLock(QMutex::Recursive), m_callback(QString(
"NOTSET"))
43 #if !defined(QT_NO_IPV6)
44 QHostAddress addr(host);
45 if ((addr.protocol() == QAbstractSocket::IPv6Protocol) ||
47 host =
"[" + host +
"]";
50 m_callback = QString(
"http://%1:%2/Subscriptions/event?usn=")
51 .arg(host).arg(QString::number(port));
58 while (!usns.isEmpty())
63 LOG(VB_UPNP, LOG_DEBUG,
LOC +
"Finished");
69 LOG(VB_UPNP, LOG_DEBUG,
LOC + QString(
"Subscribe %1 %2 %3")
70 .arg(usn).arg(url.toString()).arg(path));
83 LOG(VB_GENERAL, LOG_WARNING,
LOC +
84 "Re-subscribing with different url and path.");
103 QString uuid = QString();
121 LOG(VB_UPNP, LOG_DEBUG,
LOC + QString(
"Renew: %1").arg(usn));
137 LOG(VB_UPNP, LOG_ERR,
LOC + QString(
"Unrecognised renewal usn: %1")
148 LOG(VB_UPNP, LOG_ERR,
LOC + QString(
"No uuid - not renewing usn: %1")
162 LOG(VB_UPNP, LOG_INFO,
LOC + QString(
"Removing %1").arg(usn));
179 LOG(VB_UPNP, LOG_DEBUG,
LOC + QString(
"%1\n%2")
191 if (nt.isEmpty() || nts.isEmpty() || !no)
198 if (nt !=
"upnp:event" || nts !=
"upnp:propchange")
203 if (usn.isEmpty() || sid.isEmpty())
216 int loc = pRequest->
m_sPayload.lastIndexOf(
"propertyset>");
217 QString payload = (loc > -1) ? pRequest->
m_sPayload.left(loc + 12) :
220 LOG(VB_UPNP, LOG_DEBUG,
LOC + QString(
"Payload:\n%1").arg(payload));
227 if (!body.setContent(payload,
true, &error, &errorLine, &errorCol))
229 LOG(VB_GENERAL, LOG_ERR,
LOC +
230 QString(
"Failed to parse event: Line: %1 Col: %2 Error: '%3'")
231 .arg(errorLine).arg(errorCol).arg(error));
235 LOG(VB_UPNP, LOG_DEBUG,
LOC +
"/n/n" + body.toString(4) +
"/n/n");
237 QDomNodeList properties = body.elementsByTagName(
"property");
238 QHash<QString,QString>
results;
242 for (
int i = 0; i < properties.size(); i++)
244 QDomNodeList arguments = properties.at(i).childNodes();
245 for (
int j = 0; j < arguments.size(); j++)
247 QDomElement e = arguments.at(j).toElement();
248 if (!e.isNull() && !e.text().isEmpty() && !e.tagName().isEmpty())
249 results.insert(e.tagName(), e.text());
256 if (!results.isEmpty())
259 results.insert(
"usn", usn);
260 results.insert(
"seq", seq);
273 bool success =
false;
274 QString host = url.host();
275 int port = url.port();
278 QTextStream
data(&sub);
279 data.setCodec(QTextCodec::codecForName(
"UTF-8"));
281 data << QString(
"UNSUBSCRIBE %1 HTTP/1.1\r\n").arg(path);
282 data << QString(
"HOST: %1:%2\r\n").arg(host).arg(QString::number(port));
283 data << QString(
"SID: uuid:%1\r\n").arg(uuid);
287 LOG(VB_UPNP, LOG_DEBUG,
LOC +
"\n\n" + sub);
293 if (sock->
Connect(QHostAddress(host), port))
297 QString line = sock->
ReadLine(MAX_WAIT);
298 success = !line.isEmpty();
302 LOG(VB_GENERAL, LOG_ERR,
LOC +
303 QString(
"Socket write error for %1:%2") .arg(host).arg(port));
309 LOG(VB_GENERAL, LOG_ERR,
LOC +
310 QString(
"Failed to open socket for %1:%2") .arg(host).arg(port));
316 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Unsubscribed to %1").arg(usn));
318 LOG(VB_UPNP, LOG_WARNING,
LOC + QString(
"Failed to unsubscribe to %1")
327 const QString &uuidin,
330 QString host = url.host();
331 int port = url.port();
334 QTextStream
data(&sub);
335 data.setCodec(QTextCodec::codecForName(
"UTF-8"));
337 data << QString(
"SUBSCRIBE %1 HTTP/1.1\r\n").arg(path);
338 data << QString(
"HOST: %1:%2\r\n").arg(host).arg(QString::number(port));
341 if (uuidin.isEmpty())
343 data << QString(
"CALLBACK: <%1%2>\r\n")
344 .arg(callback).arg(usn);
345 data <<
"NT: upnp:event\r\n";
348 data << QString(
"SID: uuid:%1\r\n").arg(uuidin);
350 data << QString(
"TIMEOUT: Second-%1\r\n").arg(SUBSCRIPTION_TIME);
354 LOG(VB_UPNP, LOG_DEBUG,
LOC +
"\n\n" + sub);
364 if (sock->
Connect(QHostAddress(host), port))
369 QString line = sock->
ReadLine(MAX_WAIT);
370 while (!line.isEmpty())
372 LOG(VB_UPNP, LOG_DEBUG,
LOC + line);
373 if (line.contains(
"HTTP/1.1 200 OK", Qt::CaseInsensitive))
375 if (line.startsWith(
"SID:", Qt::CaseInsensitive))
376 uuid = line.mid(4).trimmed().mid(5).trimmed();
377 if (line.startsWith(
"TIMEOUT:", Qt::CaseInsensitive))
378 timeout = line.mid(8).trimmed().mid(7).trimmed();
379 if (ok && !uuid.isEmpty() && !timeout.isEmpty())
384 if (ok && !uuid.isEmpty() && !timeout.isEmpty())
387 result = timeout.toUInt();
391 LOG(VB_GENERAL, LOG_ERR,
LOC +
392 QString(
"Failed to subscribe to %1").arg(usn));
397 LOG(VB_GENERAL, LOG_ERR,
LOC +
398 QString(
"Socket write error for %1:%2") .arg(host).arg(port));
404 LOG(VB_GENERAL, LOG_ERR,
LOC +
405 QString(
"Failed to open socket for %1:%2") .arg(host).arg(port));