📄 gena_device.c
字号:
http_parser_t response;
int return_code = -1;
membuffer_init( &mid_msg );
// make 'end' msg (the part that won't vary with the destination)
endmsg.size_inc = 30;
if( http_MakeMessage( &mid_msg, 1, 1,
"s" "ssc" "sdcc",
headers,
"SID: ", sub->sid,
"SEQ: ", sub->ToSendEventKey ) != 0 ) {
membuffer_destroy( &mid_msg );
return UPNP_E_OUTOF_MEMORY;
}
// send a notify to each url until one goes thru
for( i = 0; i < sub->DeliveryURLs.size; i++ ) {
url = &sub->DeliveryURLs.parsedURLs[i];
// MTY !!!
/*
printf("a URL:\n\t%d\n\t%s\n\t%d\n\t%s\n\t%s\n\t%d\n", url->type,
url->scheme, url->path_type,
url->pathquery, url->fragment,
url->hostport.IPv4address);
*/
if( ( return_code = notify_send_and_recv( url,
&mid_msg, propertySet,
&response ) ) ==
UPNP_E_SUCCESS ) {
break;
}
}
membuffer_destroy( &mid_msg );
if( return_code == UPNP_E_SUCCESS ) {
if( response.msg.status_code == HTTP_OK ) {
return_code = GENA_SUCCESS;
} else {
if( response.msg.status_code == HTTP_PRECONDITION_FAILED ) {
//Invalid SID gets removed
return_code = GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB;
} else {
return_code = GENA_E_NOTIFY_UNACCEPTED;
}
}
httpmsg_destroy( &response.msg );
}
return return_code;
}
/****************************************************************************
* Function : genaNotifyThread
*
* Parameters :
* IN void * input : notify thread structure containing all the
* headers and property set info
*
* Description : Thread job to Notify a control point. It validates the
* subscription and copies the subscription. Also make sure that
* events are sent in order.
*
* Return : void
*
* Note : calls the genaNotify to do the actual work
****************************************************************************/
static void
genaNotifyThread( IN void *input )
{
subscription *sub;
service_info *service;
subscription sub_copy;
notify_thread_struct *in = ( notify_thread_struct * ) input;
int return_code;
struct Handle_Info *handle_info;
ThreadPoolJob job;
HandleLock( );
//validate context
if( GetHandleInfo( in->device_handle, &handle_info ) != HND_DEVICE ) {
free_notify_struct( in );
HandleUnlock( );
return;
}
if( ( ( service = FindServiceId( &handle_info->ServiceTable,
in->servId, in->UDN ) ) == NULL )
|| ( !service->active )
|| ( ( sub = GetSubscriptionSID( in->sid, service ) ) == NULL )
|| ( ( copy_subscription( sub, &sub_copy ) != HTTP_SUCCESS ) ) ) {
free_notify_struct( in );
HandleUnlock( );
return;
}
//If the event is out of order push it back to the job queue
if( in->eventKey != sub->ToSendEventKey ) {
TPJobInit( &job, ( start_routine ) genaNotifyThread, input );
TPJobSetFreeFunction( &job, ( free_function ) free_notify_struct );
TPJobSetPriority( &job, MED_PRIORITY );
ThreadPoolAdd( &gSendThreadPool, &job, NULL );
freeSubscription( &sub_copy );
HandleUnlock( );
return;
}
HandleUnlock( );
//send the notify
return_code = genaNotify( in->headers, in->propertySet, &sub_copy );
freeSubscription( &sub_copy );
HandleLock( );
if( GetHandleInfo( in->device_handle, &handle_info ) != HND_DEVICE ) {
free_notify_struct( in );
HandleUnlock( );
return;
}
//validate context
if( ( ( service = FindServiceId( &handle_info->ServiceTable,
in->servId, in->UDN ) ) == NULL )
|| ( !service->active )
|| ( ( sub = GetSubscriptionSID( in->sid, service ) ) == NULL ) ) {
free_notify_struct( in );
HandleUnlock( );
return;
}
sub->ToSendEventKey++;
if( sub->ToSendEventKey < 0 ) //wrap to 1 for overflow
sub->ToSendEventKey = 1;
if( return_code == GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB ) {
RemoveSubscriptionSID( in->sid, service );
}
free_notify_struct( in );
HandleUnlock( );
}
/****************************************************************************
* Function : genaNotifyBroadcastThread
*
* Parameters :
* IN void * input : notify thread structure containing all the
* headers and property set info
*
* Description : Thread job to broadcast Notifies to all control points.
*
* Return : void
*
* Note : calls the genaNotify to do the actual work
****************************************************************************/
static void
genaNotifyBroadcastThread( IN void *input )
{
notify_thread_struct *in = ( notify_thread_struct * ) input;
int return_code;
// ThreadPoolJob job;
char msgBuf[2000];
uri_type url;
membuffer mid_msg;
membuffer start_msg;
membuffer endmsg;
//printf("genaNotifyBroadcastThread\n");
membuffer_init( &mid_msg );
membuffer_init( &start_msg );
// make 'end' msg (the part that won't vary with the destination)
endmsg.size_inc = 30;
if( http_MakeMessage( &mid_msg, 1, 1,
"s" "ssc" "sdcc",
in->headers,
"SID: ", "0",
"SEQ: ", "0" ) != 0 ) {
membuffer_destroy( &mid_msg );
return UPNP_E_OUTOF_MEMORY;
}
url.type = 0;
url.scheme.buff = "http";
url.scheme.size = strlen(url.scheme.buff);
url.path_type = 4;
url.pathquery.buff = 0;
url.pathquery.size = 0;
url.fragment.buff = 0;
url.fragment.size = 0;
url.hostport.text.buff = "192.168.1.204:49152";
url.hostport.text.size = strlen(url.hostport.text.buff);
if( http_MakeMessage( &start_msg, 1, 1,
"q" "s",
HTTPMETHOD_NOTIFY, &url, mid_msg.buf ) != 0 ) {
membuffer_destroy( &start_msg );
membuffer_destroy( &mid_msg );
return UPNP_E_OUTOF_MEMORY;
}
msgBuf[0] = 0;
strcat(msgBuf, start_msg.buf);
membuffer_destroy( &mid_msg );
membuffer_destroy( &start_msg );
// strcat(msgBuf, in->headers);
strcat(msgBuf, "\n");
strcat(msgBuf, in->propertySet);
//send the notify
return_code = GenaBroadcastNotifyHandler( msgBuf );
free_notifyMulticast_struct( in );
}
/****************************************************************************
* Function : genaInitNotify
*
* Parameters :
* IN UpnpDevice_Handle device_handle : Device handle
* IN char *UDN : Device udn
* IN char *servId : Service ID
* IN char **VarNames : Array of variable names
* IN char **VarValues : Array of variable values
* IN int var_count : array size
* IN Upnp_SID sid : subscription ID
*
* Description : This function sends the intial state table dump to
* newly subscribed control point.
*
* Return : int
* returns GENA_E_SUCCESS if successful else returns appropriate error
*
* Note : No other event will be sent to this control point before the
* intial state table dump.
****************************************************************************/
int
genaInitNotify( IN UpnpDevice_Handle device_handle,
IN char *UDN,
IN char *servId,
IN char **VarNames,
IN char **VarValues,
IN int var_count,
IN Upnp_SID sid )
{
char *UDN_copy = NULL;
char *servId_copy = NULL;
char *propertySet = NULL;
char *headers = NULL;
subscription *sub = NULL;
service_info *service = NULL;
int return_code = GENA_SUCCESS;
int headers_size;
int *reference_count = NULL;
struct Handle_Info *handle_info;
ThreadPoolJob job;
notify_thread_struct *thread_struct = NULL;
DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"GENA BEGIN INITIAL NOTIFY " ) );
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 );
HandleLock( );
if( GetHandleInfo( device_handle, &handle_info ) != HND_DEVICE ) {
free( UDN_copy );
free( reference_count );
free( servId_copy );
HandleUnlock( );
return GENA_E_BAD_HANDLE;
}
if( ( service = FindServiceId( &handle_info->ServiceTable,
servId, UDN ) ) == NULL ) {
free( UDN_copy );
free( reference_count );
free( servId_copy );
HandleUnlock( );
return GENA_E_BAD_SERVICE;
}
DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"FOUND SERVICE IN INIT NOTFY: UDN %s, ServID: %d ",
UDN, servId ) );
if( ( ( sub = GetSubscriptionSID( sid, service ) ) == NULL ) ||
( sub->active ) ) {
free( UDN_copy );
free( reference_count );
free( servId_copy );
HandleUnlock( );
return GENA_E_BAD_SID;
}
DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"FOUND SUBSCRIPTION IN INIT NOTIFY: SID %s ",
sid ) );
sub->active = 1;
if( ( return_code = GeneratePropertySet( VarNames, VarValues,
var_count,
&propertySet ) ) !=
XML_SUCCESS ) {
free( UDN_copy );
free( reference_count );
free( servId_copy );
HandleUnlock( );
return return_code;
}
DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"GENERATED PROPERY SET IN INIT NOTIFY: \n'%s'\n",
propertySet ) );
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 ) {
ixmlFreeDOMString( propertySet );
free( UDN_copy );
free( servId_copy );
free( reference_count );
HandleUnlock( );
return UPNP_E_OUTOF_MEMORY;
}
sprintf( headers, "CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: "
"%d\r\nNT: upnp:event\r\nNTS: upnp:propchange\r\n",
strlen( propertySet ) + 1 );
//schedule thread for initial notification
thread_struct =
( notify_thread_struct * )
malloc( sizeof( notify_thread_struct ) );
if( thread_struct == NULL ) {
return_code = UPNP_E_OUTOF_MEMORY;
} else {
( *reference_count ) = 1;
thread_struct->servId = servId_copy;
thread_struct->UDN = UDN_copy;
thread_struct->headers = headers;
thread_struct->propertySet = propertySet;
strcpy( thread_struct->sid, sid );
thread_struct->eventKey = sub->eventKey++;
thread_struct->reference_count = reference_count;
thread_struct->device_handle = device_handle;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -