📄 gena_device.c
字号:
int headers_size;
int return_code = GENA_SUCCESS;
char *UDN_copy = NULL;
char *servId_copy = NULL;
int *reference_count = NULL;
struct Handle_Info *handle_info;
ThreadPoolJob job;
subscription *finger = NULL;
notify_thread_struct *thread_struct = NULL;
service_info *service = NULL;
reference_count = ( int * )malloc( sizeof( int ) );
if( reference_count == NULL ) {
return UPNP_E_OUTOF_MEMORY;
}
( *reference_count = 0 );
UDN_copy = ( char * )malloc( strlen( UDN ) + 1 );
if( UDN_copy == NULL ) {
free( reference_count );
return UPNP_E_OUTOF_MEMORY;
}
servId_copy = ( char * )malloc( strlen( servId ) + 1 );
if( servId_copy == NULL ) {
free( UDN_copy );
free( reference_count );
return UPNP_E_OUTOF_MEMORY;
}
strcpy( UDN_copy, UDN );
strcpy( servId_copy, servId );
if( ( return_code = GeneratePropertySet( VarNames, VarValues,
var_count,
&propertySet ) ) !=
XML_SUCCESS ) {
free( UDN_copy );
free( servId_copy );
free( reference_count );
return return_code;
}
headers_size = strlen( "CONTENT-TYPE text/xml\r\n" ) +
strlen( "CONTENT-LENGTH: \r\n" ) + MAX_CONTENT_LENGTH +
strlen( "NT: upnp:event\r\n" ) +
strlen( "NTS: upnp:propchange\r\n" ) + 1;
headers = ( char * )malloc( headers_size );
if( headers == NULL ) {
free( UDN_copy );
free( servId_copy );
ixmlFreeDOMString( propertySet );
free( reference_count );
return UPNP_E_OUTOF_MEMORY;
}
//changed to add null terminator at end of content
//content length = (length in bytes of property set) + null char
sprintf( headers, "CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\nNT:"
" upnp:event\r\nNTS: upnp:propchange\r\n",
strlen( propertySet ) + 1 );
HandleLock( );
if( GetHandleInfo( device_handle, &handle_info ) != HND_DEVICE ) {
return_code = GENA_E_BAD_HANDLE;
} else {
if( ( service = FindServiceId( &handle_info->ServiceTable,
servId, UDN ) ) != NULL ) {
finger = GetFirstSubscription( service );
while( finger ) {
thread_struct =
( notify_thread_struct * )
malloc( sizeof( notify_thread_struct ) );
if( thread_struct == NULL ) {
return_code = UPNP_E_OUTOF_MEMORY;
break;
}
( *reference_count )++;
thread_struct->reference_count = reference_count;
thread_struct->UDN = UDN_copy;
thread_struct->servId = servId_copy;
thread_struct->headers = headers;
thread_struct->propertySet = propertySet;
strcpy( thread_struct->sid, finger->sid );
thread_struct->eventKey = finger->eventKey++;
thread_struct->device_handle = device_handle;
//if overflow, wrap to 1
if( finger->eventKey < 0 ) {
finger->eventKey = 1;
}
TPJobInit( &job, ( start_routine ) genaNotifyThread,
thread_struct );
TPJobSetFreeFunction( &job,
( free_routine )
free_notify_struct );
TPJobSetPriority( &job, MED_PRIORITY );
if( ( return_code =
ThreadPoolAdd( &gSendThreadPool, &job, NULL ) )
!= 0 ) {
if( return_code == EOUTOFMEM ) {
return_code = UPNP_E_OUTOF_MEMORY;
break;
}
}
finger = GetNextSubscription( service, finger );
}
} else {
return_code = GENA_E_BAD_SERVICE;
}
}
if( ( *reference_count ) == 0 ) {
free( reference_count );
free( headers );
ixmlFreeDOMString( propertySet );
free( UDN_copy );
free( servId_copy );
}
HandleUnlock( );
return return_code;
}
/****************************************************************************
* Function : genaNotifyBroadcast
*
* Parameters :
* IN UpnpDevice_Handle device_handle : Device handle
* IN char *UDN : Device udn
* IN char *servId : Service ID
* IN char **VarNames : array of varible names
* IN char **VarValues : array of variable values
* IN int var_count : number of variables
*
* Description : This function broadcasts a notification
*
* Return : int
*
****************************************************************************/
int
genaNotifyBroadcast( IN UpnpDevice_Handle device_handle,
IN char *UDN,
IN char *servId,
IN char **VarNames,
IN char **VarValues,
IN int var_count )
{
char *headers = NULL;
char *propertySet = NULL;
int headers_size;
int return_code = GENA_SUCCESS;
char *UDN_copy = NULL;
int *reference_count = NULL;
// struct Handle_Info *handle_info;
// ThreadPoolJob job;
notify_thread_struct *thread_struct = NULL;
reference_count = ( int * )malloc( sizeof( int ) );
if( reference_count == NULL ) {
return UPNP_E_OUTOF_MEMORY;
}
( *reference_count = 0 );
UDN_copy = ( char * )malloc( strlen( UDN ) + 1 );
if( UDN_copy == NULL ) {
free( reference_count );
return UPNP_E_OUTOF_MEMORY;
}
strcpy( UDN_copy, UDN );
if( ( return_code = GeneratePropertySet( VarNames, VarValues,
var_count,
&propertySet ) ) !=
XML_SUCCESS ) {
free( UDN_copy );
free( reference_count );
return return_code;
}
headers_size = strlen( "CONTENT-TYPE text/xml\r\n" ) +
strlen( "CONTENT-LENGTH: \r\n" ) + MAX_CONTENT_LENGTH +
strlen( "NT: \r\n" ) + strlen(UDN) +
strlen( "NTS: \r\n" ) + strlen(servId) + 1;
headers = ( char * )malloc( headers_size );
if( headers == NULL ) {
free( UDN_copy );
ixmlFreeDOMString( propertySet );
free( reference_count );
return UPNP_E_OUTOF_MEMORY;
}
//changed to add null terminator at end of content
//content length = (length in bytes of property set) + null char
sprintf( headers, "CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\nNT:"
" %s\r\nNTS: %s\r\n",
strlen( propertySet ) + 1, UDN, servId );
HandleLock( );
thread_struct =
( notify_thread_struct * )
malloc( sizeof( notify_thread_struct ) );
if( thread_struct == NULL ) {
return_code = UPNP_E_OUTOF_MEMORY;
}
thread_struct->reference_count = reference_count;
thread_struct->UDN = UDN_copy;
thread_struct->headers = headers;
thread_struct->propertySet = propertySet;
/*
TPJobInit( &job, ( start_routine ) genaNotifyBroadcastThread,
thread_struct );
TPJobSetFreeFunction( &job,
( free_routine )
free_notifyMulticast_struct );
TPJobSetPriority( &job, MED_PRIORITY );
if( ( return_code =
ThreadPoolAdd( &gSendThreadPool, &job, NULL ) )
!= 0 ) {
if( return_code == EOUTOFMEM ) {
return_code = UPNP_E_OUTOF_MEMORY;
}
} else {
*/
genaNotifyBroadcastThread( thread_struct );
*reference_count = 1;
return_code = UPNP_E_SUCCESS;
// }
/*
if( ( *reference_count ) == 0 ) {
*/
free( reference_count );
free( headers );
ixmlFreeDOMString( propertySet );
free( UDN_copy );
/*
}
*/
HandleUnlock( );
return return_code;
}
/****************************************************************************
* Function : respond_ok
*
* Parameters :
* IN SOCKINFO *info : socket connection of request
* IN int time_out : accepted duration
* IN subscription *sub : accepted subscription
* IN http_message_t* request : http request
*
* Description : Function to return OK message in the case
* of a subscription request.
*
* Return : static int
* returns UPNP_E_SUCCESS if successful else returns appropriate error
* Note :
****************************************************************************/
static int
respond_ok( IN SOCKINFO * info,
IN int time_out,
IN subscription * sub,
IN http_message_t * request )
{
int major,
minor;
membuffer response;
int return_code;
char timeout_str[100];
int upnp_timeout = UPNP_TIMEOUT;
http_CalcResponseVersion( request->major_version,
request->minor_version, &major, &minor );
if( time_out >= 0 ) {
sprintf( timeout_str, "TIMEOUT: Second-%d", time_out );
} else {
strcpy( timeout_str, "TIMEOUT: Second-infinite" );
}
membuffer_init( &response );
response.size_inc = 30;
if( http_MakeMessage( &response, major, minor,
"R" "D" "S" "ssc" "sc" "c",
HTTP_OK,
"SID: ", sub->sid, timeout_str ) != 0 ) {
membuffer_destroy( &response );
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
return UPNP_E_OUTOF_MEMORY;
}
return_code = http_SendMessage( info, &upnp_timeout, "b",
response.buf, response.length );
membuffer_destroy( &response );
return return_code;
}
/****************************************************************************
* Function : create_url_list
*
* Parameters :
* IN memptr* url_list :
* OUT URL_list *out :
*
* Description : Function to parse the Callback header value in
* subscription requests takes in a buffer containing URLS delimited by
* '<' and '>'. The entire buffer is copied into dynamic memory
* and stored in the URL_list. Pointers to the individual urls within
* this buffer are allocated and stored in the URL_list. Only URLs with
* network addresses are considered(i.e. host:port or domain name)
*
* Return : int
* if successful returns the number of URLs parsed
* else UPNP_E_OUTOF_MEMORY
* Note :
****************************************************************************/
static int
create_url_list( IN memptr * url_list,
OUT URL_list * out )
{
int URLcount = 0;
int i;
int return_code = 0;
uri_type temp;
token urls;
token *URLS;
urls.buff = url_list->buf;
urls.size = url_list->length;
URLS = &urls;
out->size = 0;
out->URLs = NULL;
out->parsedURLs = NULL;
for( i = 0; i < URLS->size; i++ ) {
if( ( URLS->buff[i] == '<' ) && ( i + 1 < URLS->size ) ) {
if( ( ( return_code = parse_uri( &URLS->buff[i + 1],
URLS->size - i + 1,
&temp ) ) == HTTP_SUCCESS )
&& ( temp.hostport.text.size != 0 ) ) {
URLcount++;
} else {
if( return_code == UPNP_E_OUTOF_MEMORY ) {
return return_code;
}
}
}
}
if( URLcount > 0 ) {
out->URLs = ( char * )malloc( URLS->size + 1 );
out->parsedURLs =
( uri_type * ) malloc( sizeof( uri_type ) * URLcount );
if( ( out->URLs == NULL ) || ( out->parsedURLs == NULL ) ) {
free( out->URLs );
free( out->parsedURLs );
out->URLs = NULL;
out->parsedURLs = NULL;
return UPNP_E_OUTOF_MEMORY;
}
memcpy( out->URLs, URLS->buff, URLS->size );
out->URLs[URLS->size] = 0;
URLcount = 0;
for( i = 0; i < URLS->size; i++ ) {
if( ( URLS->buff[i] == '<' ) && ( i + 1 < URLS->size ) ) {
if( ( ( return_code =
parse_uri( &out->URLs[i + 1], URLS->size - i + 1,
&out->parsedURLs[URLcount] ) ) ==
HTTP_SUCCESS )
&& ( out->parsedURLs[URLcount].hostport.text.size !=
0 ) ) {
URLcount++;
} else {
if( return_code == UPNP_E_OUTOF_MEMORY ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -