* Improve error checking for UPnP events.
This commit is contained in:
parent
12257dff81
commit
2383bd97fe
154
upnphttp.c
154
upnphttp.c
@ -88,6 +88,12 @@
|
||||
|
||||
#include "icons.c"
|
||||
|
||||
enum event_type {
|
||||
E_INVALID,
|
||||
E_SUBSCRIBE,
|
||||
E_RENEW
|
||||
};
|
||||
|
||||
struct upnphttp *
|
||||
New_upnphttp(int s)
|
||||
{
|
||||
@ -210,9 +216,6 @@ ParseHttpHeaders(struct upnphttp * h)
|
||||
n++;
|
||||
h->req_Callback = p + 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)
|
||||
{
|
||||
@ -741,74 +744,119 @@ ProcessHTTPPOST_upnphttp(struct upnphttp * h)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
check_event(struct upnphttp *h)
|
||||
{
|
||||
enum event_type type;
|
||||
|
||||
if (h->req_Callback)
|
||||
{
|
||||
if (h->req_SID || !h->req_NT)
|
||||
{
|
||||
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.
|
||||
* If CALLBACK header is missing or does not contain a valid HTTP URL,
|
||||
* the publisher must respond with HTTP error 412 Precondition Failed*/
|
||||
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
||||
type = E_INVALID;
|
||||
}
|
||||
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);
|
||||
if((!h->req_Callback && !h->req_SID) ||
|
||||
strncmp(h->req_NT, "upnp:event", h->req_NTLen) != 0) {
|
||||
/* Missing or invalid CALLBACK : 412 Precondition Failed.
|
||||
* If CALLBACK header is missing or does not contain a valid HTTP URL,
|
||||
* the publisher must respond with HTTP error 412 Precondition Failed*/
|
||||
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
||||
SendResp_upnphttp(h);
|
||||
CloseSocket_upnphttp(h);
|
||||
} else {
|
||||
/* - add to the subscriber list
|
||||
* - respond HTTP/x.x 200 OK
|
||||
* - Send the initial event message */
|
||||
/* 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,
|
||||
h->req_CallbackLen, h->req_Timeout);
|
||||
h->respflags = FLAG_TIMEOUT;
|
||||
if(sid) {
|
||||
DPRINTF(E_DEBUG, L_HTTP, "generated sid=%s\n", sid);
|
||||
h->respflags |= FLAG_SID;
|
||||
h->req_SID = sid;
|
||||
h->req_SIDLen = strlen(sid);
|
||||
}
|
||||
BuildResp_upnphttp(h, 0, 0);
|
||||
}
|
||||
} else {
|
||||
/* subscription renew */
|
||||
/* Invalid SID
|
||||
412 Precondition Failed. If a SID does not correspond to a known,
|
||||
un-expired subscription, the publisher must respond
|
||||
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);
|
||||
} else {
|
||||
/* A DLNA device must enforce a 5 minute timeout */
|
||||
h->respflags = FLAG_TIMEOUT;
|
||||
h->req_Timeout = 300;
|
||||
h->respflags |= FLAG_SID;
|
||||
BuildResp_upnphttp(h, 0, 0);
|
||||
}
|
||||
|
||||
type = check_event(h);
|
||||
if (type == E_SUBSCRIBE)
|
||||
{
|
||||
/* - add to the subscriber list
|
||||
* - respond HTTP/x.x 200 OK
|
||||
* - Send the initial event message */
|
||||
/* Server:, SID:; Timeout: Second-(xx|infinite) */
|
||||
sid = upnpevents_addSubscriber(path, h->req_Callback,
|
||||
h->req_CallbackLen, h->req_Timeout);
|
||||
h->respflags = FLAG_TIMEOUT;
|
||||
if (sid)
|
||||
{
|
||||
DPRINTF(E_DEBUG, L_HTTP, "generated sid=%s\n", sid);
|
||||
h->respflags |= FLAG_SID;
|
||||
h->req_SID = sid;
|
||||
h->req_SIDLen = strlen(sid);
|
||||
}
|
||||
SendResp_upnphttp(h);
|
||||
CloseSocket_upnphttp(h);
|
||||
BuildResp_upnphttp(h, 0, 0);
|
||||
}
|
||||
else if (type == E_RENEW)
|
||||
{
|
||||
/* subscription renew */
|
||||
if (renewSubscription(h->req_SID, h->req_SIDLen, h->req_Timeout) < 0)
|
||||
{
|
||||
/* Invalid SID
|
||||
412 Precondition Failed. If a SID does not correspond to a known,
|
||||
un-expired subscription, the publisher must respond
|
||||
with HTTP error 412 Precondition Failed. */
|
||||
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A DLNA device must enforce a 5 minute timeout */
|
||||
h->respflags = FLAG_TIMEOUT;
|
||||
h->req_Timeout = 300;
|
||||
h->respflags |= FLAG_SID;
|
||||
BuildResp_upnphttp(h, 0, 0);
|
||||
}
|
||||
}
|
||||
SendResp_upnphttp(h);
|
||||
CloseSocket_upnphttp(h);
|
||||
}
|
||||
|
||||
static void
|
||||
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, "SID '%.*s'\n", h->req_SIDLen, h->req_SID);
|
||||
/* Remove from the list */
|
||||
if(upnpevents_removeSubscriber(h->req_SID, h->req_SIDLen) < 0) {
|
||||
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
||||
} else {
|
||||
BuildResp_upnphttp(h, 0, 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);
|
||||
else
|
||||
BuildResp_upnphttp(h, 0, 0);
|
||||
}
|
||||
SendResp_upnphttp(h);
|
||||
CloseSocket_upnphttp(h);
|
||||
|
Loading…
x
Reference in New Issue
Block a user