📄 soap_device.c
字号:
if( BodyNode == NULL ) {
goto error_handler;
}
// Got action node here
ActNode = ixmlNode_getFirstChild( BodyNode );
if( ActNode == NULL ) {
goto error_handler;
}
//Test whether this is the action node
nodeName = ixmlNode_getNodeName( ActNode );
if( nodeName == NULL ) {
goto error_handler;
}
if( strstr( nodeName, NodeName ) == NULL ) {
goto error_handler;
} else {
ActNodeName = ixmlPrintDocument( ActNode );
if( ActNodeName == NULL ) {
goto error_handler;
}
ret_code = ixmlParseBufferEx( ActNodeName, RespNode );
if( ret_code != IXML_SUCCESS ) {
ixmlFreeDOMString( ActNodeName );
ret_code = -1;
goto error_handler;
}
}
ret_code = 0; // success
error_handler:
ixmlFreeDOMString( ActNodeName );
if( nl )
ixmlNodeList_free( nl );
return ret_code;
}
/****************************************************************************
* Function : check_soap_body
*
* Parameters :
* IN IXML_Document *doc : soap body xml document
* IN const char *urn :
* IN const char *actionName : Name of the requested action
*
* Description : This function checks the soap body xml came in the
* SOAP request.
*
* Return : int
* UPNP_E_SUCCESS if successful else returns appropriate error
*
* Note :
****************************************************************************/
static int
check_soap_body( IN IXML_Document * doc,
IN const char *urn,
IN const char *actionName )
{
IXML_NodeList *nl = NULL;
IXML_Node *bodyNode = NULL;
IXML_Node *actionNode = NULL;
const DOMString ns = NULL;
const DOMString name = NULL;
int ret_code = UPNP_E_INVALID_ACTION;
nl = ixmlDocument_getElementsByTagNameNS( doc, SOAP_URN, SOAP_BODY );
if( nl ) {
bodyNode = ixmlNodeList_item( nl, 0 );
if( bodyNode ) {
actionNode = ixmlNode_getFirstChild( bodyNode );
if( actionNode ) {
ns = ixmlNode_getNamespaceURI( actionNode );
name = ixmlNode_getLocalName( actionNode );
if( ( !strcmp( actionName, name ) )
&& ( !strcmp( urn, ns ) ) ) {
ret_code = UPNP_E_SUCCESS;
}
}
}
ixmlNodeList_free( nl );
}
return ret_code;
}
/****************************************************************************
* Function : check_soap_action_header
*
* Parameters :
* IN http_message_t *request : HTTP request
* IN const char *urn :
* OUT char **actionName : name of the SOAP action
*
* Description : This function checks the HTTP header of the SOAP request
* coming from the control point
*
* Return : static int
* UPNP_E_SUCCESS if successful else returns appropriate error
*
* Note :
****************************************************************************/
static int
check_soap_action_header( IN http_message_t * request,
IN const char *urn,
OUT char **actionName )
{
memptr header_name;
http_header_t *soap_action_header = NULL;
char *ns_compare = NULL;
int tempSize = 0;
int ret_code = UPNP_E_SUCCESS;
char *temp_header_value = NULL;
char *temp = NULL;
char *temp2 = NULL;
//check soap action header
soap_action_header = httpmsg_find_hdr( request, HDR_SOAPACTION,
&header_name );
if( !soap_action_header ) {
ret_code = UPNP_E_INVALID_ACTION;
return ret_code;
}
if( soap_action_header->value.length <= 0 ) {
ret_code = UPNP_E_INVALID_ACTION;
return ret_code;
}
temp_header_value =
( char * )malloc( soap_action_header->value.length + 1 );
if( !temp_header_value ) {
ret_code = UPNP_E_OUTOF_MEMORY;
free( temp_header_value );
return ret_code;
}
strncpy( temp_header_value, soap_action_header->value.buf,
soap_action_header->value.length );
temp_header_value[soap_action_header->value.length] = 0;
temp = strchr( temp_header_value, '#' );
if( !temp ) {
free( temp_header_value );
ret_code = UPNP_E_INVALID_ACTION;
return ret_code;
}
( *temp ) = 0; //temp make string
//check to see if it is Query State Variable or
//Service Action
tempSize = strlen( urn ) + 2;
ns_compare = ( char * )malloc( tempSize );
if( !ns_compare ) {
ret_code = UPNP_E_OUTOF_MEMORY;
free( temp_header_value );
return ret_code;
}
_snprintf( ns_compare, tempSize, "\"%s", urn );
if( strcmp( temp_header_value, ns_compare ) ) {
ret_code = UPNP_E_INVALID_ACTION;
} else {
ret_code = UPNP_E_SUCCESS;
temp++;
temp2 = strchr( temp, '\"' );
if( temp2 ) //remove ending " if present
{
( *temp2 ) = 0;
}
if( *temp )
( *actionName ) = strdup( temp );
if( !*actionName ) {
ret_code = UPNP_E_OUTOF_MEMORY;
}
}
free( temp_header_value );
free( ns_compare );
return ret_code;
}
/****************************************************************************
* Function : get_device_info
*
* Parameters :
* IN http_message_t* request : HTTP request
* IN int isQuery : flag for a querry
* IN IXML_Document *actionDoc : action request document
* OUT char device_udn[LINE_SIZE] : Device UDN string
* OUT char service_id[LINE_SIZE] : Service ID string
* OUT Upnp_FunPtr *callback : callback function of the device
* application
* OUT void** cookie : cookie stored by device application
*
* Description : This function retrives all the information needed to
* process the incoming SOAP request. It finds the device and service info
* and also the callback function to hand-over the request to the device
* application.
*
* Return : int
* UPNP_E_SUCCESS if successful else returns appropriate error
*
* Note :
****************************************************************************/
static int
get_device_info( IN http_message_t * request,
IN int isQuery,
IN IXML_Document * actionDoc,
OUT char device_udn[LINE_SIZE],
OUT char service_id[LINE_SIZE],
OUT Upnp_FunPtr * callback,
OUT void **cookie )
{
struct Handle_Info *device_info;
int device_hnd;
service_info *serv_info;
char save_char;
int ret_code = -1; // error by default
char *control_url;
char *actionName = NULL;
// null-terminate pathquery of url
control_url = request->uri.pathquery.buff;
save_char = control_url[request->uri.pathquery.size];
control_url[request->uri.pathquery.size] = '\0';
HandleLock( );
if( GetDeviceHandleInfo( &device_hnd, &device_info ) != HND_DEVICE ) {
goto error_handler;
}
if( ( serv_info =
FindServiceControlURLPath( &device_info->ServiceTable,
control_url ) ) == NULL ) {
goto error_handler;
}
if( isQuery ) {
ret_code = check_soap_action_header( request, QUERY_STATE_VAR_URN,
&actionName );
if( ( ret_code != UPNP_E_SUCCESS )
&& ( ret_code != UPNP_E_OUTOF_MEMORY ) ) {
ret_code = UPNP_E_INVALID_ACTION;
goto error_handler;
}
//check soap body
ret_code =
check_soap_body( actionDoc, QUERY_STATE_VAR_URN, actionName );
free( actionName );
if( ret_code != UPNP_E_SUCCESS ) {
goto error_handler;
}
} else {
ret_code = check_soap_action_header( request,
serv_info->serviceType,
&actionName );
if( ( ret_code != UPNP_E_SUCCESS )
&& ( ret_code != UPNP_E_OUTOF_MEMORY ) ) {
ret_code = UPNP_E_INVALID_SERVICE;
goto error_handler;
}
//check soap body
ret_code =
check_soap_body( actionDoc, serv_info->serviceType,
actionName );
free( actionName );
if( ret_code != UPNP_E_SUCCESS ) {
ret_code = UPNP_E_INVALID_SERVICE;
goto error_handler;
}
}
namecopy( service_id, serv_info->serviceId );
namecopy( device_udn, serv_info->UDN );
*callback = device_info->Callback;
*cookie = device_info->Cookie;
ret_code = 0;
error_handler:
control_url[request->uri.pathquery.size] = save_char; // restore
HandleUnlock( );
return ret_code;
}
/****************************************************************************
* Function : send_action_response
*
* Parameters :
* IN SOCKINFO *info : socket info
* IN IXML_Document *action_resp : The response document
* IN http_message_t* request : action request document
*
* Description : This function sends the SOAP response
*
* Return : void
*
* Note :
****************************************************************************/
static XINLINE void
send_action_response( IN SOCKINFO * info,
IN IXML_Document * action_resp,
IN http_message_t * request )
{
char *xml_response = NULL;
membuffer headers;
int major,
minor;
int err_code;
int content_length;
int ret_code;
int timeout_secs = SOAP_TIMEOUT;
static char *start_body =
"<?xml version=\"1.0\"?>\n<s:Envelope xmlns:s=\"http://schemas.xmlsoap."
"org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap."
"org/soap/encoding/\">\n<s:Body>\n";
static char *end_body = "</s:Body>\n</s:Envelope>\n\n";
// init
http_CalcResponseVersion( request->major_version,
request->minor_version, &major, &minor );
membuffer_init( &headers );
err_code = UPNP_E_OUTOF_MEMORY; // one error only
// get xml
xml_response = ixmlPrintDocument( ( IXML_Node * ) action_resp );
if( xml_response == NULL ) {
goto error_handler;
}
content_length = strlen( start_body ) + strlen( xml_response ) +
strlen( end_body );
// make headers
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -