📄 soap_device.c
字号:
if( http_MakeMessage( &headers, major, minor, "RNsDsSc", HTTP_OK, // status code
content_length, ContentTypeHeader, "EXT:\n" // EXT header
) != 0 ) {
goto error_handler;
}
// send whole msg
ret_code = http_SendMessage( info, &timeout_secs, "bbbb",
headers.buf, headers.length,
start_body, strlen( start_body ),
xml_response, strlen( xml_response ),
end_body, strlen( end_body ) );
DBGONLY( if( ret_code != 0 ) {
UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
"Failed to send response: err code = %d\n",
ret_code );}
)
err_code = 0;
error_handler:
ixmlFreeDOMString( xml_response );
membuffer_destroy( &headers );
if( err_code != 0 ) {
// only one type of error to worry about - out of mem
send_error_response( info, SOAP_ACTION_FAILED, "Out of memory",
request );
}
}
/****************************************************************************
* Function : get_var_name
*
* Parameters :
* IN IXML_Document *TempDoc : Document containing variable request
* OUT char* VarName : Name of the state varible
*
* Description : This function finds the name of the state variable
* asked in the SOAP request.
*
* Return : int
* returns 0 if successful else returns -1.
* Note :
****************************************************************************/
static XINLINE int
get_var_name( IN IXML_Document * TempDoc,
OUT char *VarName )
{
IXML_Node *EnvpNode = NULL;
IXML_Node *BodyNode = NULL;
IXML_Node *StNode = NULL;
IXML_Node *VarNameNode = NULL;
IXML_Node *VarNode = NULL;
const DOMString StNodeName = NULL;
DOMString Temp = NULL;
int ret_val = -1;
// Got the Envelop node here
EnvpNode = ixmlNode_getFirstChild( ( IXML_Node * ) TempDoc );
if( EnvpNode == NULL ) {
goto error_handler;
}
// Got Body here
BodyNode = ixmlNode_getFirstChild( EnvpNode );
if( BodyNode == NULL ) {
goto error_handler;
}
// Got action node here
StNode = ixmlNode_getFirstChild( BodyNode );
if( StNode == NULL ) {
goto error_handler;
}
//Test whether this is the action node
StNodeName = ixmlNode_getNodeName( StNode );
if( StNodeName == NULL || strstr( StNodeName,
"QueryStateVariable" ) == NULL ) {
goto error_handler;
}
VarNameNode = ixmlNode_getFirstChild( StNode );
if( VarNameNode == NULL ) {
goto error_handler;
}
VarNode = ixmlNode_getFirstChild( VarNameNode );
Temp = ixmlNode_getNodeValue( VarNode );
linecopy( VarName, Temp );
DBGONLY( UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
"Received query for variable name %s\n",
VarName );
)
ret_val = 0; // success
error_handler:
return ret_val;
}
/****************************************************************************
* Function : handle_query_variable
*
* Parameters :
* IN SOCKINFO *info : Socket info
* IN http_message_t* request : HTTP request
* IN IXML_Document *xml_doc : Document containing the variable request
* SOAP message
*
* Description : This action handles the SOAP requests to querry the
* state variables. This functionality has been deprecated in
* the UPnP V1.0 architecture
*
* Return : void
*
* Note :
****************************************************************************/
static XINLINE void
handle_query_variable( IN SOCKINFO * info,
IN http_message_t * request,
IN IXML_Document * xml_doc )
{
Upnp_FunPtr soap_event_callback;
void *cookie;
char var_name[LINE_SIZE];
struct Upnp_State_Var_Request variable;
const char *err_str;
int err_code;
// get var name
if( get_var_name( xml_doc, var_name ) != 0 ) {
send_error_response( info, SOAP_INVALID_VAR,
Soap_Invalid_Var, request );
return;
}
// get info for event
if( get_device_info( request, 1, xml_doc, variable.DevUDN,
variable.ServiceID,
&soap_event_callback, &cookie ) != 0 ) {
send_error_response( info, SOAP_INVALID_VAR,
Soap_Invalid_Var, request );
return;
}
linecopy( variable.ErrStr, "" );
variable.ErrCode = UPNP_E_SUCCESS;
namecopy( variable.StateVarName, var_name );
variable.CurrentVal = NULL;
variable.CtrlPtIPAddr = info->foreign_ip_addr;
// send event
soap_event_callback( UPNP_CONTROL_GET_VAR_REQUEST, &variable, cookie );
DBGONLY( UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
"Return from callback for var request\n" ) );
// validate, and handle result
if( variable.CurrentVal == NULL ) {
err_code = SOAP_ACTION_FAILED;
err_str = Soap_Action_Failed;
send_error_response( info, SOAP_INVALID_VAR,
Soap_Invalid_Var, request );
return;
}
if( variable.ErrCode != UPNP_E_SUCCESS ) {
if( strlen( variable.ErrStr ) > 0 ) {
err_code = SOAP_INVALID_VAR;
err_str = Soap_Invalid_Var;
} else {
err_code = variable.ErrCode;
err_str = variable.ErrStr;
}
send_error_response( info, err_code, err_str, request );
return;
}
// send response
send_var_query_response( info, variable.CurrentVal, request );
ixmlFreeDOMString( variable.CurrentVal );
}
/****************************************************************************
* Function : handle_invoke_action
*
* Parameters :
* IN SOCKINFO *info : Socket info
* IN http_message_t* request : HTTP Request
* IN memptr action_name : Name of the SOAP Action
* IN IXML_Document *xml_doc : document containing the SOAP action
* request
*
* Description : This functions handle the SOAP action request. It checks
* the integrity of the SOAP action request and gives the call back to
* the device application.
*
* Return : void
*
* Note :
****************************************************************************/
static void
handle_invoke_action( IN SOCKINFO * info,
IN http_message_t * request,
IN memptr action_name,
IN IXML_Document * xml_doc )
{
char save_char;
IXML_Document *resp_node = NULL;
struct Upnp_Action_Request action;
Upnp_FunPtr soap_event_callback;
void *cookie = NULL;
int err_code;
const char *err_str;
action.ActionResult = NULL;
// null-terminate
save_char = action_name.buf[action_name.length];
action_name.buf[action_name.length] = '\0';
// set default error
err_code = SOAP_INVALID_ACTION;
err_str = Soap_Invalid_Action;
// get action node
if( get_action_node( xml_doc, action_name.buf, &resp_node ) == -1 ) {
goto error_handler;
}
// get device info for action event
err_code = get_device_info( request, 0, xml_doc, action.DevUDN,
action.ServiceID, &soap_event_callback,
&cookie );
if( err_code != UPNP_E_SUCCESS ) {
goto error_handler;
}
namecopy( action.ActionName, action_name.buf );
linecopy( action.ErrStr, "" );
action.ActionRequest = resp_node;
action.ActionResult = NULL;
action.ErrCode = UPNP_E_SUCCESS;
action.CtrlPtIPAddr = info->foreign_ip_addr;
DBGONLY( UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
"Calling Callback\n" ) );
soap_event_callback( UPNP_CONTROL_ACTION_REQUEST, &action, cookie );
if( action.ErrCode != UPNP_E_SUCCESS ) {
if( strlen( action.ErrStr ) <= 0 ) {
err_code = SOAP_ACTION_FAILED;
err_str = Soap_Action_Failed;
} else {
err_code = action.ErrCode;
err_str = action.ErrStr;
}
goto error_handler;
}
// validate, and handle action error
if( action.ActionResult == NULL ) {
err_code = SOAP_ACTION_FAILED;
err_str = Soap_Action_Failed;
goto error_handler;
}
// send response
send_action_response( info, action.ActionResult, request );
err_code = 0;
// error handling and cleanup
error_handler:
ixmlDocument_free( action.ActionResult );
ixmlDocument_free( resp_node );
action_name.buf[action_name.length] = save_char; // restore
if( err_code != 0 ) {
send_error_response( info, err_code, err_str, request );
}
}
/****************************************************************************
* Function : soap_device_callback
*
* Parameters :
* IN http_parser_t *parser : Parsed request received by the device
* IN http_message_t* request : HTTP request
* INOUT SOCKINFO *info : socket info
*
* Description : This is a callback called by minisever after receiving
* the request from the control point. This function will start
* processing the request. It calls handle_invoke_action to handle the
* SOAP action
*
* Return : void
*
* Note :
****************************************************************************/
void
soap_device_callback( IN http_parser_t * parser,
IN http_message_t * request,
INOUT SOCKINFO * info )
{
int err_code;
const char *err_str;
memptr action_name;
IXML_Document *xml_doc = NULL;
// set default error
err_code = SOAP_INVALID_ACTION;
err_str = Soap_Invalid_Action;
// validate: content-type == text/xml
if( !has_xml_content_type( request ) ) {
goto error_handler;
}
// type of request
if( get_request_type( request, &action_name ) != 0 ) {
goto error_handler;
}
// parse XML
err_code = ixmlParseBufferEx( request->entity.buf, &xml_doc );
if( err_code != IXML_SUCCESS ) {
if( err_code == IXML_INSUFFICIENT_MEMORY ) {
err_code = UPNP_E_OUTOF_MEMORY;
} else {
err_code = SOAP_ACTION_FAILED;
}
err_str = "XML error";
goto error_handler;
}
if( action_name.length == 0 ) {
// query var
handle_query_variable( info, request, xml_doc );
} else {
// invoke action
handle_invoke_action( info, request, action_name, xml_doc );
}
err_code = 0; // no error
error_handler:
ixmlDocument_free( xml_doc );
if( err_code != 0 ) {
send_error_response( info, err_code, err_str, request );
}
}
#endif // EXCLUDE_SOAP
#endif // INCLUDE_DEVICE_APIS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -