📄 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"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 voidGenaAutoRenewSubscription( 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 intScheduleGenaAutoRenew( 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, 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 intgena_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 intgena_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 *sid = str_alloc( sid_hdr.buf, sid_hdr.length ); if( *sid == NULL ) { httpmsg_destroy( &response.msg ); return UPNP_E_OUTOF_MEMORY; } httpmsg_destroy( &response.msg ); return UPNP_E_SUCCESS;}/************************************************************************* Function : genaUnregisterClient * * Parameters: * IN UpnpClient_Handle client_handle: Handle containing all the control* point related information** Description: * This function unsubcribes all the outstanding subscriptions and cleans* the subscription list. This function is called when control point * unregisters.** Returns: int* return UPNP_E_SUCCESS if successful else returns appropriate error***************************************************************************/intgenaUnregisterClient( IN UpnpClient_Handle client_handle ){ client_subscription sub_copy; int return_code = UPNP_E_SUCCESS; struct Handle_Info *handle_info = NULL; http_parser_t response; while( TRUE ) { HandleLock( ); if( GetHandleInfo( client_handle, &handle_info ) != HND_CLIENT ) { HandleUnlock( ); return GENA_E_BAD_HANDLE; } if( handle_info->ClientSubList == NULL ) { return_code = UPNP_E_SUCCESS; break; } return_code = copy_client_subscription( handle_info->ClientSubList, &sub_copy ); if( return_code != HTTP_SUCCESS ) { break; } RemoveClientSubClientSID( &handle_info->ClientSubList, sub_copy.sid ); HandleUnlock( ); return_code = gena_unsubscribe( sub_copy.EventURL, sub_copy.ActualSID, &response ); if( return_code == 0 ) { httpmsg_destroy( &response.msg ); } free_client_subscription( &sub_copy ); } freeClientSubList( handle_info->ClientSubList ); HandleUnlock( ); return return_code;}/************************************************************************* Function : genaUnSubscribe* * Parameters: * IN UpnpClient_Handle client_handle: UPnP client handle* IN SID in_sid: The subscription ID*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -