📄 gena_device.c
字号:
free( out->URLs );
free( out->parsedURLs );
out->URLs = NULL;
out->parsedURLs = NULL;
return return_code;
}
}
}
}
}
out->size = URLcount;
return URLcount;
}
/****************************************************************************
* Function : gena_process_subscription_request
*
* Parameters :
* IN SOCKINFO *info : socket info of the device
* IN http_message_t* request : SUBSCRIPTION request from the control
* point
*
* Description : This function handles a subscription request from a
* ctrl point. The socket is not closed on return.
*
* Return : void
*
* Note :
****************************************************************************/
void
gena_process_subscription_request( IN SOCKINFO * info,
IN http_message_t * request )
{
Upnp_SID temp_sid;
int return_code = 1;
int time_out = 1801;
service_info *service;
struct Upnp_Subscription_Request request_struct;
subscription *sub;
uuid_upnp uid;
struct Handle_Info *handle_info;
void *cookie;
Upnp_FunPtr callback_fun;
UpnpDevice_Handle device_handle;
memptr nt_hdr;
char *event_url_path = NULL;
memptr callback_hdr;
memptr timeout_hdr;
DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"Subscription Request Received:\n" ) );
if( httpmsg_find_hdr( request, HDR_NT, &nt_hdr ) == NULL ) {
error_respond( info, HTTP_BAD_REQUEST, request );
return;
}
// check NT header
//Windows Millenium Interoperability:
//we accept either upnp:event, or upnp:propchange for the NT header
if( memptr_cmp_nocase( &nt_hdr, "upnp:event" ) != 0 ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request );
return;
}
// if a SID is present then the we have a bad request
// "incompatible headers"
if( httpmsg_find_hdr( request, HDR_SID, NULL ) != NULL ) {
error_respond( info, HTTP_BAD_REQUEST, request );
return;
}
//look up service by eventURL
if( ( event_url_path = str_alloc( request->uri.pathquery.buff,
request->uri.pathquery.size ) ) ==
NULL ) {
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
return;
}
DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"SubscriptionRequest for event URL path: %s\n",
event_url_path );
)
HandleLock( );
// CURRENTLY, ONLY ONE DEVICE
if( GetDeviceHandleInfo( &device_handle, &handle_info ) != HND_DEVICE ) {
free( event_url_path );
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
HandleUnlock( );
return;
}
service = FindServiceEventURLPath( &handle_info->ServiceTable,
event_url_path );
free( event_url_path );
if( service == NULL || !service->active ) {
error_respond( info, HTTP_NOT_FOUND, request );
HandleUnlock( );
return;
}
DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"Subscription Request: Number of Subscriptions already %d\n "
"Max Subscriptions allowed: %d\n",
service->TotalSubscriptions,
handle_info->MaxSubscriptions ) );
// too many subscriptions
if( handle_info->MaxSubscriptions != -1 &&
service->TotalSubscriptions >= handle_info->MaxSubscriptions ) {
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
HandleUnlock( );
return;
}
// generate new subscription
sub = ( subscription * ) malloc( sizeof( subscription ) );
if( sub == NULL ) {
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
HandleUnlock( );
return;
}
sub->eventKey = 0;
sub->ToSendEventKey = 0;
sub->active = 0;
sub->next = NULL;
sub->DeliveryURLs.size = 0;
sub->DeliveryURLs.URLs = NULL;
sub->DeliveryURLs.parsedURLs = NULL;
// check for valid callbacks
if( httpmsg_find_hdr( request, HDR_CALLBACK, &callback_hdr ) == NULL ||
( return_code = create_url_list( &callback_hdr,
&sub->DeliveryURLs ) ) == 0 ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request );
freeSubscriptionList( sub );
HandleUnlock( );
return;
}
if( return_code == UPNP_E_OUTOF_MEMORY ) {
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
freeSubscriptionList( sub );
HandleUnlock( );
return;
}
// set the timeout
if( httpmsg_find_hdr( request, HDR_TIMEOUT, &timeout_hdr ) != NULL ) {
if( matchstr( timeout_hdr.buf, timeout_hdr.length,
"%iSecond-%d%0", &time_out ) == PARSE_OK ) {
// nothing
} else if( memptr_cmp_nocase( &timeout_hdr, "Second-infinite" ) ==
0 ) {
time_out = -1; // infinite timeout
} else {
time_out = DEFAULT_TIMEOUT; // default is > 1800 seconds
}
}
// replace infinite timeout with max timeout, if possible
if( handle_info->MaxSubscriptionTimeOut != -1 ) {
if( time_out == -1 ||
time_out > handle_info->MaxSubscriptionTimeOut ) {
time_out = handle_info->MaxSubscriptionTimeOut;
}
}
if( time_out >= 0 ) {
sub->expireTime = time( NULL ) + time_out;
} else {
sub->expireTime = 0; // infinite time
}
//generate SID
uuid_create( &uid );
uuid_unpack( &uid, temp_sid );
sprintf( sub->sid, "uuid:%s", temp_sid );
// respond OK
if( respond_ok( info, time_out, sub, request ) != UPNP_E_SUCCESS ) {
freeSubscriptionList( sub );
HandleUnlock( );
return;
}
//add to subscription list
sub->next = service->subscriptionList;
service->subscriptionList = sub;
service->TotalSubscriptions++;
//finally generate callback for init table dump
request_struct.ServiceId = service->serviceId;
request_struct.UDN = service->UDN;
strcpy( ( char * )request_struct.Sid, sub->sid );
//copy callback
callback_fun = handle_info->Callback;
cookie = handle_info->Cookie;
HandleUnlock( );
//make call back with request struct
//in the future should find a way of mainting
//that the handle is not unregistered in the middle of a
//callback
callback_fun( UPNP_EVENT_SUBSCRIPTION_REQUEST,
&request_struct, cookie );
}
/****************************************************************************
* Function : gena_process_subscription_renewal_request
*
* Parameters :
* IN SOCKINFO *info : socket info of the device
* IN http_message_t* request : subscription renewal request from the
* control point
*
* Description : This function handles a subscription renewal request
* from a ctrl point. The connection is not destroyed on return.
*
* Return : void
*
* Note :
****************************************************************************/
void
gena_process_subscription_renewal_request( IN SOCKINFO * info,
IN http_message_t * request )
{
Upnp_SID sid;
subscription *sub;
int time_out = 1801;
service_info *service;
struct Handle_Info *handle_info;
UpnpDevice_Handle device_handle;
memptr temp_hdr;
membuffer event_url_path;
memptr timeout_hdr;
// if a CALLBACK or NT header is present, then it is an error
if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL ||
httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) {
error_respond( info, HTTP_BAD_REQUEST, request );
return;
}
// get SID
if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL ||
temp_hdr.length > SID_SIZE ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request );
return;
}
memcpy( sid, temp_hdr.buf, temp_hdr.length );
sid[temp_hdr.length] = '\0';
// lookup service by eventURL
membuffer_init( &event_url_path );
if( membuffer_append( &event_url_path, request->uri.pathquery.buff,
request->uri.pathquery.size ) != 0 ) {
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
return;
}
HandleLock( );
// CURRENTLY, ONLY SUPPORT ONE DEVICE
if( GetDeviceHandleInfo( &device_handle, &handle_info ) != HND_DEVICE ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request );
membuffer_destroy( &event_url_path );
return;
}
service = FindServiceEventURLPath( &handle_info->ServiceTable,
event_url_path.buf );
membuffer_destroy( &event_url_path );
// get subscription
if( service == NULL ||
!service->active ||
( ( sub = GetSubscriptionSID( sid, service ) ) == NULL ) ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request );
HandleUnlock( );
return;
}
DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"Renew request: Number of subscriptions already: %d\n "
"Max Subscriptions allowed:%d\n",
service->TotalSubscriptions,
handle_info->MaxSubscriptions );
)
// too many subscriptions
if( handle_info->MaxSubscriptions != -1 &&
service->TotalSubscriptions > handle_info->MaxSubscriptions ) {
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
RemoveSubscriptionSID( sub->sid, service );
HandleUnlock( );
return;
}
// set the timeout
if( httpmsg_find_hdr( request, HDR_TIMEOUT, &timeout_hdr ) != NULL ) {
if( matchstr( timeout_hdr.buf, timeout_hdr.length,
"%iSecond-%d%0", &time_out ) == PARSE_OK ) {
//nothing
} else if( memptr_cmp_nocase( &timeout_hdr, "Second-infinite" ) ==
0 ) {
time_out = -1; // inifinite timeout
} else {
time_out = DEFAULT_TIMEOUT; // default is > 1800 seconds
}
}
// replace infinite timeout with max timeout, if possible
if( handle_info->MaxSubscriptionTimeOut != -1 ) {
if( time_out == -1 ||
time_out > handle_info->MaxSubscriptionTimeOut ) {
time_out = handle_info->MaxSubscriptionTimeOut;
}
}
if( time_out == -1 ) {
sub->expireTime = 0;
} else {
sub->expireTime = time( NULL ) + time_out;
}
if( respond_ok( info, time_out, sub, request ) != UPNP_E_SUCCESS ) {
RemoveSubscriptionSID( sub->sid, service );
}
HandleUnlock( );
}
/****************************************************************************
* Function : gena_process_unsubscribe_request
*
* Parameters :
* IN SOCKINFO *info : socket info of the device
* IN http_message_t* request : UNSUBSCRIBE request from the control
* point
*
* Description : This function Handles a subscription cancellation request
* from a ctrl point. The connection is not destroyed on return.
*
* Return : void
*
* Note :
****************************************************************************/
void
gena_process_unsubscribe_request( IN SOCKINFO * info,
IN http_message_t * request )
{
Upnp_SID sid;
service_info *service;
struct Handle_Info *handle_info;
UpnpDevice_Handle device_handle;
memptr temp_hdr;
membuffer event_url_path;
// if a CALLBACK or NT header is present, then it is an error
if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL ||
httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) {
error_respond( info, HTTP_BAD_REQUEST, request );
return;
}
// get SID
if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL ||
temp_hdr.length > SID_SIZE ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request );
return;
}
memcpy( sid, temp_hdr.buf, temp_hdr.length );
sid[temp_hdr.length] = '\0';
// lookup service by eventURL
membuffer_init( &event_url_path );
if( membuffer_append( &event_url_path, request->uri.pathquery.buff,
request->uri.pathquery.size ) != 0 ) {
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
return;
}
HandleLock( );
// CURRENTLY, ONLY SUPPORT ONE DEVICE
if( GetDeviceHandleInfo( &device_handle, &handle_info ) != HND_DEVICE ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request );
membuffer_destroy( &event_url_path );
HandleUnlock( );
return;
}
service = FindServiceEventURLPath( &handle_info->ServiceTable,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -