📄 subs.cpp
字号:
// Returns: TRUE if successful, FALSE if not. GetLastError() contains the
// error code.
//
// Author: danielwe 12 Oct 1999
//
// Notes:
//
BOOL FAddSubscriberFromRequest(SSDP_REQUEST * pRequest, PSTR *ppResp, DWORD dwIndex)
{
BOOL fResult = FALSE;
UPNP_EVENT_SOURCE * pes;
UPNP_SUBSCRIBER * pSub = NULL;
AssertSz(pRequest->Method == GENA_SUBSCRIBE, "I thought you told me "
"this was a subscription request!");
// First, do some checking on the message headers to see if this is a
// valid subscription request
//
if (!pRequest->Headers[GENA_CALLBACK])
{
pRequest->status = HTTP_STATUS_BAD_REQUEST;
TraceTag(ttidEvents, "Didn't get a Callback header!");
SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
return FALSE;
}
if (!pRequest->RequestUri || !(*pRequest->RequestUri))
{
TraceTag(ttidEvents, "Didn't get a Reqeust-Uri!");
pRequest->status = HTTP_STATUS_BAD_REQUEST;
SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
return FALSE;
}
EnterCriticalSection(&g_csListEventSource);
pes = PesFindEventSource(pRequest->RequestUri);
if (!pes)
{
pRequest->status =HTTP_STATUS_SERVER_ERROR;
TraceTag(ttidEvents, "Subscription sent to unknown Request URI: %s ",
pRequest->RequestUri);
// No event source registered matches this Request URI. We'll
// retrun 404 Not Found.
//
SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
goto cleanupL;
}
// Found the event source this SUBSCRIBE was sent to
//
pSub = (UPNP_SUBSCRIBER *) malloc(sizeof(UPNP_SUBSCRIBER));
if (!pSub)
{
SetLastError(ERROR_OUTOFMEMORY);
goto cleanupL;
}
memset(pSub,0,sizeof(UPNP_SUBSCRIBER));
// Validate the Callback header and look for at least one URL that
// starts with "http://"
//
if (!FParseCallbackUrl(pRequest->Headers[GENA_CALLBACK], &pSub->szDestUrl))
{
TraceTag(ttidEvents, "Callback header '%s' was invalid!",
pRequest->Headers[GENA_CALLBACK]);
pRequest->status = HTTP_STATUS_PRECOND_FAILED;
SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
goto cleanupL;
}
DWORD dw;
if(!FixURLAddressScopeId(pSub->szDestUrl, dwIndex, NULL, &(dw = 0)) && dw != 0)
if(char* szDestUrl = (char*)malloc(dw))
if(FixURLAddressScopeId(pSub->szDestUrl, dwIndex, szDestUrl, &dw))
{
free(pSub->szDestUrl);
pSub->szDestUrl = szDestUrl;
}
else
free(szDestUrl);
if(!g_pURL_Verifier->is_url_ok(pSub->szDestUrl))
{
TraceTag(ttidEvents, "Callback url '%s' is invalid.", pSub->szDestUrl);
pRequest->status = HTTP_STATUS_PRECOND_FAILED;
SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
goto cleanupL;
}
pSub->hEventCleanup = CreateEvent(NULL, TRUE, FALSE, NULL);
// Fill in some of the other members of the subscription struct
//
pSub->dwEventTimeout = DEFAULT_EVENT_TIMEOUT;
pSub->flags = 0;
pSub->pes = pes;
pSub->iSeq = 0;
pSub->szSid = SzGetNewSid();
if (!pSub->szSid)
{
SetLastError(ERROR_OUTOFMEMORY);
goto cleanupL;
}
if(pes->cProps)
{
pSub->rgesModified = (bool*)malloc(sizeof(bool) * pes->cProps);
if (!pSub->rgesModified)
{
SetLastError(ERROR_OUTOFMEMORY);
goto cleanupL;
}
pSub->cProps = pes->cProps;
}
pSub->dwTimerCookie = 0;
pSub->fInTimer = FALSE;
// Ok, now we have a valid subscription, so we need to send a response
// to the subscriber
SetSubscriptionTimeout(pSub, pRequest->Headers[GENA_TIMEOUT]);
if (*ppResp = ComposeSubscribeResponse(pSub))
{
LPSTR szSid;
DWORD iSeq;
// Must hold the event source lock across adding the subscriber and
// sending the notify message
//EnterCriticalSection(&pes->cs);
szSid = _strdup(pSub->szSid);
iSeq = pSub->iSeq;
// Ok we've added the subscription and notified so it's ok to allow
// pre-empting now
#if DBG
PrintSubscription(pSub);
#endif
//PersistSubscriberList();
AddToListSubscriber(pes, pSub);
StartResubscribeTimer(pSub);
//LeaveCriticalSection(&pes->cs);
LeaveCriticalSection(&g_csListEventSource);
// hack to make the SID available to the caller
// so that an initial event notification can be sent
pRequest->Headers[GENA_SID] = szSid;
// tell UPNP device about this subscription
// this callback also gives the device a chance to update the evented variables
if (pfSubscribeCallback)
if (!pfSubscribeCallback(TRUE, pRequest->RequestUri))
{
// subscription was vetoed
pRequest->Method = GENA_UNSUBSCRIBE;
FRemoveSubscriberFromRequest(pRequest, NULL);
pRequest->Method = GENA_SUBSCRIBE;
pRequest->status = HTTP_STATUS_SERVICE_UNAVAIL;
return FALSE;
}
fResult = TRUE;
}
else
goto cleanupL;
TraceResult("FAddSubscriberFromRequest", fResult);
return fResult;
cleanupL:
FreeUpnpSubscriber(pSub);
LeaveCriticalSection(&g_csListEventSource);
return FALSE;
}
//+---------------------------------------------------------------------------
//
// Function: SendInitialEventNotification
//
// Purpose: Send the initial event notification to a subscriber
//
//
DWORD SendInitialEventNotification(PSSDP_REQUEST pRequest)
{
LPSTR szBody = NULL;
AssertSz(pRequest->Method == GENA_SUBSCRIBE, "I thought you told me "
"this was a subscribe request!");
AssertSz(pRequest->Headers[GENA_SID], "Why don't I have a SID header??!?!");
if (!pRequest->RequestUri || !(*pRequest->RequestUri))
{
TraceTag(ttidEvents, "Didn't get a Reqeust-Uri!");
FreeSsdpRequest(pRequest);
delete pRequest;
return 0;
}
EnterCriticalSection(&g_csListEventSource);
// Find the event source based on the URI
//
if(UPNP_EVENT_SOURCE *pes = PesFindEventSource(pRequest->RequestUri))
{
//EnterCriticalSection(&pes->cs);
PLIST_ENTRY pListHead = &pes->listSubs;
UPNP_SUBSCRIBER *pSub = NULL;
// Found the event source this SUBSCRIBE was sent to. Now find the
// subscriber.
for (PLIST_ENTRY p = pListHead->Flink; p != pListHead; p = p->Flink)
{
pSub = CONTAINING_RECORD (p, UPNP_SUBSCRIBER, linkage);
if (!_stricmp(pSub->szSid, pRequest->Headers[GENA_SID]))
{
// Found the subscriber they were looking for!
break;
}
}
if (p != pListHead)
{
Assert(pSub);
AssertSz(pSub->iSeq == 0, "Can't send initial notify if sequence number is not 0!");
if(EventData* pEvent = new EventData)
{
// make a copy of the destination URL and SID since we can't touch the subscriber
// fields after leaving the Critical Section.
pEvent->strUrl = pSub->szDestUrl;
pEvent->strSid = pSub->szSid;
pEvent->iSeq = pSub->iSeq;
pEvent->dwTimeout = pSub->dwEventTimeout;
pEvent->hEventSent = NULL;
// create event body
if(SUCCEEDED(HrComposeXmlBodyFromEventSource(pes, pSub, pSub->iSeq == 0, &pEvent->pszBody)))
{
// mark that we are in process of sending event to the subscriber
assert(!(pSub->flags & F_UPNPSUB_SENDING_EVENT));
pSub->flags |= F_UPNPSUB_SENDING_EVENT;
LeaveCriticalSection(&g_csListEventSource);
SendEventMessage(pEvent);
EnterCriticalSection(&g_csListEventSource);
}
else
delete pEvent;
}
}
//LeaveCriticalSection(&pes->cs);
}
LeaveCriticalSection(&g_csListEventSource);
if (szBody)
free(szBody);
FreeSsdpRequest(pRequest);
delete pRequest;
return 0;
}
//+---------------------------------------------------------------------------
//
// Function: FRemoveSubscriberFromRequest
//
// Purpose: Given an UNSUBSCRIBE request, removes the subscription from
// the list within the event source.
//
// Arguments:
//
// pRequest [in] Request to be processed
// ppResp [out] Response
//
// Returns: TRUE if successful, FALSE if not. GetLastError() contains the
// error code.
//
// Author: danielwe 13 Oct 1999
//
// Notes:
//
BOOL FRemoveSubscriberFromRequest(SSDP_REQUEST * pRequest, PSTR *)
{
BOOL fResult = FALSE;
UPNP_EVENT_SOURCE * pes;
PLIST_ENTRY pListHead;
PLIST_ENTRY p;
AssertSz(pRequest->Method == GENA_UNSUBSCRIBE, "I thought you told me "
"this was an unsubscribe request!");
// First, do some checking on the message headers to see if this is a
// valid unsubscribe request
//
if (!pRequest->Headers[GENA_SID] || !(*(pRequest->Headers[GENA_SID])))
{
TraceTag(ttidEvents, "Didn't get a valid SID header!");
pRequest->status = HTTP_STATUS_BAD_REQUEST;
SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
goto cleanup;
}
if (!pRequest->RequestUri || !(*pRequest->RequestUri))
{
TraceTag(ttidEvents, "Didn't get a Reqeust-Uri!");
pRequest->status = HTTP_STATUS_BAD_REQUEST;
SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
goto cleanup;
}
EnterCriticalSection(&g_csListEventSource);
// Find the event source based on the URI
//
pes = PesFindEventSource(pRequest->RequestUri);
if (!pes)
{
TraceTag(ttidEvents, "Unsubscrbe sent to unknown Request URI: %s ",
pRequest->RequestUri);
// No event source registered matches this Request URI. We'll
// retrun 404 Not Found.
//
pRequest->status = HTTP_STATUS_SERVER_ERROR;
SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
goto cleanupL;
}
// Found the event source this SUBSCRIBE was sent to. Now find the
// subscriber.
//
//EnterCriticalSection(&pes->cs);
pListHead = &pes->listSubs;
for (p = pListHead->Flink; p != pListHead; p = p->Flink)
{
UPNP_SUBSCRIBER * pSub;
pSub = CONTAINING_RECORD (p, UPNP_SUBSCRIBER, linkage);
if (!_stricmp(pSub->szSid, pRequest->Headers[GENA_SID]))
{
TraceTag(ttidEvents, "Unsubscribing SID: %s ",
pRequest->Headers[GENA_SID]);
// Found the subscriber they were looking for!
//
CleanupSubscriberEntry(pSub);
//pRequest->status = HTTP_STATUS_OK;
fResult = TRUE;
break;
}
}
//LeaveCriticalSection(&pes->cs);
if (p == pListHead)
{
TraceTag(ttidEvents, "Unsubscribe sent to unknown SID: %s ",
pRequest->Headers[GENA_SID]);
// Didn't find the subscriber. We should return 404 Not Found.
pRequest->status = HTTP_STATUS_SERVER_ERROR;
SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
fResult = FALSE;
}
cleanupL:
LeaveCriticalSection(&g_csListEventSource);
// signal the unsubscribe to the upper layers
if (fResult && pfSubscribeCallback)
pfSubscribeCallback(FALSE,pRequest->RequestUri);
cleanup:
TraceResult("FRemoveSubscriberFromRequest", fResult);
return fResult;
}
//+---------------------------------------------------------------------------
//
// Function: ResubscribeTimerProc
//
// Purpose: Callback that is called when the re-subscription timer has
// run out.
//
// Arguments:
// pvContext [in] Context variable. This is the pSub pointer.
//
// Returns: Nothing
//
// Author: danielwe 13 Oct 1999
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -