📄 gena_ctrlpt.c
字号:
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2003 Intel Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include "config.h"
#if EXCLUDE_GENA == 0
#ifdef INCLUDE_CLIENT_APIS
#include "gena.h"
#include "sysdep.h"
#include "uuid.h"
#include "upnpapi.h"
#include "parsetools.h"
#include "statcodes.h"
#include "httpparser.h"
#include "httpreadwrite.h"
#include "gena_ctrlpt.h"
#ifdef _WIN32
#include <winsock2.h>
#include <Ws2tcpip.h>
#endif
SOCKET gGenaSock = UPNP_INVALID_SOCKET;
extern ithread_mutex_t GlobalClientSubscribeMutex;
/************************************************************************
* Function : GenaAutoRenewSubscription
*
* Parameters:
* IN void *input: Thread data(upnp_timeout *) needed to send the renewal
*
* Description:
* This is a thread function to send the renewal just before the
* subscription times out.
*
* Returns: VOID
*
***************************************************************************/
static void
GenaAutoRenewSubscription( IN void *input )
{
upnp_timeout *event = ( upnp_timeout * ) input;
void *cookie;
Upnp_FunPtr callback_fun;
struct Handle_Info *handle_info;
struct Upnp_Event_Subscribe *sub_struct =
( struct Upnp_Event_Subscribe * )
event->Event;
int send_callback = 0;
int eventType = 0;
if( AUTO_RENEW_TIME == 0 ) {
DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"GENA SUB EXPIRED" ) );
sub_struct->ErrCode = UPNP_E_SUCCESS;
send_callback = 1;
eventType = UPNP_EVENT_SUBSCRIPTION_EXPIRED;
} else {
DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"GENA AUTO RENEW" ) );
if( ( ( sub_struct->ErrCode = genaRenewSubscription( event->handle,
sub_struct->
Sid,
&sub_struct->
TimeOut ) ) !=
UPNP_E_SUCCESS )
&& ( sub_struct->ErrCode != GENA_E_BAD_SID )
&& ( sub_struct->ErrCode != GENA_E_BAD_HANDLE ) ) {
send_callback = 1;
eventType = UPNP_EVENT_AUTORENEWAL_FAILED;
}
}
if( send_callback ) {
HandleLock( );
if( GetHandleInfo( event->handle, &handle_info ) != HND_CLIENT ) {
HandleUnlock( );
free_upnp_timeout( event );
return;
}
DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"HANDLE IS VALID" ) );
callback_fun = handle_info->Callback;
cookie = handle_info->Cookie;
HandleUnlock( );
//make callback
callback_fun( eventType, event->Event, cookie );
}
free_upnp_timeout( event );
}
/************************************************************************
* Function : ScheduleGenaAutoRenew
*
* Parameters:
* IN int client_handle: Handle that also contains the subscription list
* IN int TimeOut: The time out value of the subscription
* IN client_subscription * sub: Subscription being renewed
*
* Description:
* This function schedules a job to renew the subscription just before
* time out.
*
* Returns: int
* return GENA_E_SUCCESS if successful else returns appropriate error
***************************************************************************/
static int
ScheduleGenaAutoRenew( IN int client_handle,
IN int TimeOut,
IN client_subscription * sub )
{
struct Upnp_Event_Subscribe *RenewEventStruct = NULL;
upnp_timeout *RenewEvent = NULL;
int return_code = GENA_SUCCESS;
ThreadPoolJob job;
if( TimeOut == UPNP_INFINITE ) {
return GENA_SUCCESS;
}
RenewEventStruct = ( struct Upnp_Event_Subscribe * )malloc( sizeof
( struct
Upnp_Event_Subscribe ) );
if( RenewEventStruct == NULL ) {
return UPNP_E_OUTOF_MEMORY;
}
RenewEvent = ( upnp_timeout * ) malloc( sizeof( upnp_timeout ) );
if( RenewEvent == NULL ) {
free( RenewEventStruct );
return UPNP_E_OUTOF_MEMORY;
}
//schedule expire event
strcpy( RenewEventStruct->Sid, sub->sid );
RenewEventStruct->ErrCode = UPNP_E_SUCCESS;
strncpy( RenewEventStruct->PublisherUrl, sub->EventURL,
UPNP_NAME_SIZE - 1 );
RenewEventStruct->TimeOut = TimeOut;
//RenewEvent->EventType=UPNP_EVENT_SUBSCRIPTION_EXPIRE;
RenewEvent->handle = client_handle;
RenewEvent->Event = RenewEventStruct;
TPJobInit( &job, ( start_routine ) GenaAutoRenewSubscription,
RenewEvent );
TPJobSetFreeFunction( &job, ( free_routine ) free_upnp_timeout );
TPJobSetPriority( &job, MED_PRIORITY );
//Schedule the job
if( ( return_code = TimerThreadSchedule( &gTimerThread,
TimeOut - AUTO_RENEW_TIME,
REL_SEC, &job, SHORT_TERM,
&( RenewEvent->
eventId ) ) ) !=
UPNP_E_SUCCESS ) {
free( RenewEvent );
free( RenewEventStruct );
return return_code;
}
sub->RenewEventId = RenewEvent->eventId;
return GENA_SUCCESS;
}
/************************************************************************
* Function : gena_unsubscribe
*
* Parameters:
* IN char *url: Event URL of the service
* IN char *sid: The subcription ID.
* OUT http_parser_t* response: The UNSUBCRIBE response from the device
*
* Description:
* This function sends the UNSUBCRIBE gena request and recieves the
* response from the device and returns it as a parameter
*
* Returns: int
* return 0 if successful else returns appropriate error
***************************************************************************/
static int
gena_unsubscribe( IN char *url,
IN char *sid,
OUT http_parser_t * response )
{
int return_code;
uri_type dest_url;
membuffer request;
// parse url
return_code = http_FixStrUrl( url, strlen( url ), &dest_url );
if( return_code != 0 ) {
return return_code;
}
// make request msg
membuffer_init( &request );
request.size_inc = 30;
return_code = http_MakeMessage( &request, 1, 1,
"q" "ssc" "U" "c",
HTTPMETHOD_UNSUBSCRIBE, &dest_url,
"SID: ", sid );
//Not able to make the message so destroy the existing buffer
if( return_code != 0 ) {
membuffer_destroy( &request );
return return_code;
}
// send request and get reply
return_code = http_RequestAndResponse( &dest_url, request.buf,
request.length,
HTTPMETHOD_UNSUBSCRIBE,
HTTP_DEFAULT_TIMEOUT,
response );
membuffer_destroy( &request );
if( return_code != 0 )
httpmsg_destroy( &response->msg );
if( return_code == 0 && response->msg.status_code != HTTP_OK ) {
return_code = UPNP_E_UNSUBSCRIBE_UNACCEPTED;
httpmsg_destroy( &response->msg );
}
return return_code;
}
/************************************************************************
* Function : gena_subscribe
*
* Parameters:
* IN char *url: url of service to subscribe
* INOUT int* timeout:subscription time desired (in secs)
* IN char* renewal_sid:for renewal, this contains a currently h
* held subscription SID. For first time
* subscription, this must be NULL
* OUT char** sid: SID returned by the subscription or renew msg
*
* Description:
* This function subscribes or renew subscription
*
* Returns: int
* return 0 if successful else returns appropriate error
***************************************************************************/
static int
gena_subscribe( IN char *url,
INOUT int *timeout,
IN char *renewal_sid,
OUT char **sid )
{
int return_code;
memptr sid_hdr,
timeout_hdr;
char timeout_str[25];
membuffer request;
uri_type dest_url;
http_parser_t response;
*sid = NULL; // init
// request timeout to string
if( ( timeout == NULL ) ||
( ( *timeout > 0 )
&& ( *timeout < CP_MINIMUM_SUBSCRIPTION_TIME ) ) ) {
sprintf( timeout_str, "%d", CP_MINIMUM_SUBSCRIPTION_TIME );
} else if( *timeout >= 0 ) {
sprintf( timeout_str, "%d", *timeout );
} else {
strcpy( timeout_str, "infinite" );
}
// parse url
return_code = http_FixStrUrl( url, strlen( url ), &dest_url );
if( return_code != 0 ) {
return return_code;
}
// make request msg
membuffer_init( &request );
request.size_inc = 30;
if( renewal_sid ) {
// renew subscription
return_code = http_MakeMessage( &request, 1, 1,
"q" "ssc" "ssc" "c",
HTTPMETHOD_SUBSCRIBE, &dest_url,
"SID: ", renewal_sid,
"TIMEOUT: Second-", timeout_str );
} else {
// subscribe
return_code = http_MakeMessage( &request, 1, 1,
"q" "sssdsscc",
HTTPMETHOD_SUBSCRIBE, &dest_url,
"CALLBACK: <http://", LOCAL_HOST,
":", LOCAL_PORT,
"/>\r\n" "NT: upnp:event\r\n"
"TIMEOUT: Second-", timeout_str );
}
if( return_code != 0 ) {
return return_code;
}
// send request and get reply
return_code = http_RequestAndResponse( &dest_url, request.buf,
request.length,
HTTPMETHOD_SUBSCRIBE,
HTTP_DEFAULT_TIMEOUT,
&response );
membuffer_destroy( &request );
if( return_code != 0 ) {
httpmsg_destroy( &response.msg );
return return_code;
}
if( response.msg.status_code != HTTP_OK ) {
httpmsg_destroy( &response.msg );
return UPNP_E_SUBSCRIBE_UNACCEPTED;
}
// get SID and TIMEOUT
if( httpmsg_find_hdr( &response.msg, HDR_SID, &sid_hdr ) == NULL ||
sid_hdr.length == 0 ||
httpmsg_find_hdr( &response.msg,
HDR_TIMEOUT, &timeout_hdr ) == NULL ||
timeout_hdr.length == 0 ) {
httpmsg_destroy( &response.msg );
return UPNP_E_BAD_RESPONSE;
}
// save timeout
if( matchstr( timeout_hdr.buf, timeout_hdr.length, "%iSecond-%d%0",
timeout ) == PARSE_OK ) {
// nothing
} else if( memptr_cmp_nocase( &timeout_hdr, "Second-infinite" ) == 0 ) {
*timeout = -1;
} else {
httpmsg_destroy( &response.msg );
return UPNP_E_BAD_RESPONSE;
}
// save SID
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -