* Improve error checking for UPnP events.
This commit is contained in:
parent
12257dff81
commit
2383bd97fe
108
upnphttp.c
108
upnphttp.c
@ -88,6 +88,12 @@
|
|||||||
|
|
||||||
#include "icons.c"
|
#include "icons.c"
|
||||||
|
|
||||||
|
enum event_type {
|
||||||
|
E_INVALID,
|
||||||
|
E_SUBSCRIBE,
|
||||||
|
E_RENEW
|
||||||
|
};
|
||||||
|
|
||||||
struct upnphttp *
|
struct upnphttp *
|
||||||
New_upnphttp(int s)
|
New_upnphttp(int s)
|
||||||
{
|
{
|
||||||
@ -210,9 +216,6 @@ ParseHttpHeaders(struct upnphttp * h)
|
|||||||
n++;
|
n++;
|
||||||
h->req_Callback = p + 1;
|
h->req_Callback = p + 1;
|
||||||
h->req_CallbackLen = MAX(0, n - 1);
|
h->req_CallbackLen = MAX(0, n - 1);
|
||||||
/* Verify callback validity */
|
|
||||||
if(strncmp(h->req_Callback, "http://", 7) != 0)
|
|
||||||
h->req_Callback = NULL;
|
|
||||||
}
|
}
|
||||||
else if(strncasecmp(line, "SID", 3)==0)
|
else if(strncasecmp(line, "SID", 3)==0)
|
||||||
{
|
{
|
||||||
@ -741,36 +744,74 @@ ProcessHTTPPOST_upnphttp(struct upnphttp * h)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path)
|
check_event(struct upnphttp *h)
|
||||||
{
|
{
|
||||||
const char * sid;
|
enum event_type type;
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "ProcessHTTPSubscribe %s\n", path);
|
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "Callback '%.*s' Timeout=%d\n",
|
if (h->req_Callback)
|
||||||
h->req_CallbackLen, h->req_Callback, h->req_Timeout);
|
{
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "SID '%.*s'\n", h->req_SIDLen, h->req_SID);
|
if (h->req_SID || !h->req_NT)
|
||||||
if((!h->req_Callback && !h->req_SID) ||
|
{
|
||||||
strncmp(h->req_NT, "upnp:event", h->req_NTLen) != 0) {
|
BuildResp2_upnphttp(h, 400, "Bad Request",
|
||||||
|
"<html><body>Bad request</body></html>", 37);
|
||||||
|
type = E_INVALID;
|
||||||
|
}
|
||||||
|
else if (strncmp(h->req_Callback, "http://", 7) != 0 ||
|
||||||
|
strncmp(h->req_NT, "upnp:event", h->req_NTLen) != 0)
|
||||||
|
{
|
||||||
/* Missing or invalid CALLBACK : 412 Precondition Failed.
|
/* Missing or invalid CALLBACK : 412 Precondition Failed.
|
||||||
* If CALLBACK header is missing or does not contain a valid HTTP URL,
|
* If CALLBACK header is missing or does not contain a valid HTTP URL,
|
||||||
* the publisher must respond with HTTP error 412 Precondition Failed*/
|
* the publisher must respond with HTTP error 412 Precondition Failed*/
|
||||||
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
||||||
SendResp_upnphttp(h);
|
type = E_INVALID;
|
||||||
CloseSocket_upnphttp(h);
|
}
|
||||||
} else {
|
else
|
||||||
|
type = E_SUBSCRIBE;
|
||||||
|
}
|
||||||
|
else if (h->req_SID)
|
||||||
|
{
|
||||||
|
/* subscription renew */
|
||||||
|
if (h->req_NT)
|
||||||
|
{
|
||||||
|
BuildResp2_upnphttp(h, 400, "Bad Request",
|
||||||
|
"<html><body>Bad request</body></html>", 37);
|
||||||
|
type = E_INVALID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
type = E_RENEW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
||||||
|
type = E_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path)
|
||||||
|
{
|
||||||
|
const char * sid;
|
||||||
|
enum event_type type;
|
||||||
|
DPRINTF(E_DEBUG, L_HTTP, "ProcessHTTPSubscribe %s\n", path);
|
||||||
|
DPRINTF(E_DEBUG, L_HTTP, "Callback '%.*s' Timeout=%d\n",
|
||||||
|
h->req_CallbackLen, h->req_Callback, h->req_Timeout);
|
||||||
|
DPRINTF(E_DEBUG, L_HTTP, "SID '%.*s'\n", h->req_SIDLen, h->req_SID);
|
||||||
|
|
||||||
|
type = check_event(h);
|
||||||
|
if (type == E_SUBSCRIBE)
|
||||||
|
{
|
||||||
/* - add to the subscriber list
|
/* - add to the subscriber list
|
||||||
* - respond HTTP/x.x 200 OK
|
* - respond HTTP/x.x 200 OK
|
||||||
* - Send the initial event message */
|
* - Send the initial event message */
|
||||||
/* Server:, SID:; Timeout: Second-(xx|infinite) */
|
/* Server:, SID:; Timeout: Second-(xx|infinite) */
|
||||||
if(h->req_Callback) {
|
|
||||||
if(!h->req_NT || strncmp(h->req_NT, "upnp:event", h->req_NTLen) != 0) {
|
|
||||||
BuildResp2_upnphttp(h, 400, "Bad Request",
|
|
||||||
"<html><body>Bad request</body></html>", 37);
|
|
||||||
} else {
|
|
||||||
sid = upnpevents_addSubscriber(path, h->req_Callback,
|
sid = upnpevents_addSubscriber(path, h->req_Callback,
|
||||||
h->req_CallbackLen, h->req_Timeout);
|
h->req_CallbackLen, h->req_Timeout);
|
||||||
h->respflags = FLAG_TIMEOUT;
|
h->respflags = FLAG_TIMEOUT;
|
||||||
if(sid) {
|
if (sid)
|
||||||
|
{
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "generated sid=%s\n", sid);
|
DPRINTF(E_DEBUG, L_HTTP, "generated sid=%s\n", sid);
|
||||||
h->respflags |= FLAG_SID;
|
h->respflags |= FLAG_SID;
|
||||||
h->req_SID = sid;
|
h->req_SID = sid;
|
||||||
@ -778,15 +819,19 @@ ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path)
|
|||||||
}
|
}
|
||||||
BuildResp_upnphttp(h, 0, 0);
|
BuildResp_upnphttp(h, 0, 0);
|
||||||
}
|
}
|
||||||
} else {
|
else if (type == E_RENEW)
|
||||||
|
{
|
||||||
/* subscription renew */
|
/* subscription renew */
|
||||||
|
if (renewSubscription(h->req_SID, h->req_SIDLen, h->req_Timeout) < 0)
|
||||||
|
{
|
||||||
/* Invalid SID
|
/* Invalid SID
|
||||||
412 Precondition Failed. If a SID does not correspond to a known,
|
412 Precondition Failed. If a SID does not correspond to a known,
|
||||||
un-expired subscription, the publisher must respond
|
un-expired subscription, the publisher must respond
|
||||||
with HTTP error 412 Precondition Failed. */
|
with HTTP error 412 Precondition Failed. */
|
||||||
if(renewSubscription(h->req_SID, h->req_SIDLen, h->req_Timeout) < 0) {
|
|
||||||
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* A DLNA device must enforce a 5 minute timeout */
|
/* A DLNA device must enforce a 5 minute timeout */
|
||||||
h->respflags = FLAG_TIMEOUT;
|
h->respflags = FLAG_TIMEOUT;
|
||||||
h->req_Timeout = 300;
|
h->req_Timeout = 300;
|
||||||
@ -796,18 +841,21 @@ with HTTP error 412 Precondition Failed. */
|
|||||||
}
|
}
|
||||||
SendResp_upnphttp(h);
|
SendResp_upnphttp(h);
|
||||||
CloseSocket_upnphttp(h);
|
CloseSocket_upnphttp(h);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ProcessHTTPUnSubscribe_upnphttp(struct upnphttp * h, const char * path)
|
ProcessHTTPUnSubscribe_upnphttp(struct upnphttp * h, const char * path)
|
||||||
{
|
{
|
||||||
|
enum event_type type;
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "ProcessHTTPUnSubscribe %s\n", path);
|
DPRINTF(E_DEBUG, L_HTTP, "ProcessHTTPUnSubscribe %s\n", path);
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "SID '%.*s'\n", h->req_SIDLen, h->req_SID);
|
DPRINTF(E_DEBUG, L_HTTP, "SID '%.*s'\n", h->req_SIDLen, h->req_SID);
|
||||||
/* Remove from the list */
|
/* Remove from the list */
|
||||||
if(upnpevents_removeSubscriber(h->req_SID, h->req_SIDLen) < 0) {
|
type = check_event(h);
|
||||||
|
if (type != E_INVALID)
|
||||||
|
{
|
||||||
|
if(upnpevents_removeSubscriber(h->req_SID, h->req_SIDLen) < 0)
|
||||||
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
||||||
} else {
|
else
|
||||||
BuildResp_upnphttp(h, 0, 0);
|
BuildResp_upnphttp(h, 0, 0);
|
||||||
}
|
}
|
||||||
SendResp_upnphttp(h);
|
SendResp_upnphttp(h);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user