📄 soap_ctrlpt.c
字号:
/////////////////////////////////////////////////////////////////////////////// Copyright (c) 2000-2003 Intel Corporation // All rights reserved. //// Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: //// * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither name of Intel Corporation nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission.// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE./////////////////////////////////////////////////////////////////////////////#include "config.h"#ifdef INCLUDE_CLIENT_APIS#if EXCLUDE_SOAP == 0#include <assert.h>#include <stdlib.h>#include <ctype.h>#include <stdio.h>#include <stdarg.h>#include "miniserver.h"#include "membuffer.h"#include "httpparser.h"#include "httpreadwrite.h"#include "statcodes.h"#include "parsetools.h"#include "upnpapi.h"#include "soaplib.h"#include "uri.h"#include "upnp.h"#include "unixutil.h"#define SOAP_ACTION_RESP 1#define SOAP_VAR_RESP 2//#define SOAP_ERROR_RESP 3#define SOAP_ACTION_RESP_ERROR 3#define SOAP_VAR_RESP_ERROR 4/***************************************************************************** Function : dom_cmp_name** Parameters :* IN char *name : lookup name* IN IXML_Node *node : xml node** Description : This function compares 'name' and node's name ** Return : int* 0 if both are equal; 1 if not equal, and UPNP_E_OUTOF_MEMORY** Note :****************************************************************************/static intdom_cmp_name( IN char *name, IN IXML_Node * node ){ const DOMString node_name = NULL; memptr nameptr, dummy; int ret_code; assert( name ); assert( node ); node_name = ixmlNode_getNodeName( node ); if( node_name == NULL ) { return UPNP_E_OUTOF_MEMORY; } if( strcmp( name, node_name ) == 0 ) { ret_code = 0; } else if( matchstr( ( char * )node_name, strlen( node_name ), "%s:%s%0", &dummy, &nameptr ) == PARSE_OK && strcmp( nameptr.buf, name ) == 0 ) { ret_code = 0; } else { ret_code = 1; // names are not the same } return ret_code;}/***************************************************************************** Function : dom_find_node** Parameters :* IN char* node_name : name of the node * IN IXML_Node *start_node : complete xml node* OUT IXML_Node ** matching_node : matched node** Description : This function goes thru each child of 'start_node' * looking for a node having the name 'node_name'. ** Return : int* return UPNP_E_SUCCESS if successful else returns appropriate error** Note :****************************************************************************/static intdom_find_node( IN char *node_name, IN IXML_Node * start_node, OUT IXML_Node ** matching_node ){ IXML_Node *node; // invalid args if( node_name == NULL || start_node == NULL ) { return UPNP_E_NOT_FOUND; } node = ixmlNode_getFirstChild( start_node ); while( node != NULL ) { // match name if( dom_cmp_name( node_name, node ) == 0 ) { *matching_node = node; return UPNP_E_SUCCESS; } // free and next node node = ixmlNode_getNextSibling( node ); // next node } return UPNP_E_NOT_FOUND;}/***************************************************************************** Function : dom_find_deep_node** Parameters :* IN char* names[] : array of names* IN int num_names : size of array* IN IXML_Node *start_node : Node from where it should should be * searched * OUT IXML_Node ** matching_node : Node that matches the last name* of the array** Description : This function searches for the node specifed by the last * name in the 'name' array.** Return : int* return UPNP_E_SUCCESS if successful else returns appropriate error* Note :****************************************************************************/static intdom_find_deep_node( IN char *names[], IN int num_names, IN IXML_Node * start_node, OUT IXML_Node ** matching_node ){ int i; IXML_Node *node; IXML_Node *match_node; assert( num_names > 0 ); node = start_node; if( dom_cmp_name( names[0], start_node ) == 0 ) { if( num_names == 1 ) { *matching_node = start_node; return UPNP_E_SUCCESS; } } for( i = 1; i < num_names; i++ ) { if( dom_find_node( names[i], node, &match_node ) != UPNP_E_SUCCESS ) { return UPNP_E_NOT_FOUND; } if( i == num_names - 1 ) { *matching_node = match_node; return UPNP_E_SUCCESS; } node = match_node; // try again } return UPNP_E_NOT_FOUND; // this line not reached}/***************************************************************************** Function : get_node_value** Parameters :* IN IXML_Node *node : input node ** Description : This function returns the value of the text node** Return : DOMString* string containing the node value** Note :The given node must have a text node as its first child****************************************************************************/static DOMStringget_node_value( IN IXML_Node * node ){ IXML_Node *text_node = NULL; DOMString text_value = NULL; text_node = ixmlNode_getFirstChild( node ); if( text_node == NULL ) { return NULL; } text_value = ixmlNode_getNodeValue( text_node ); return text_value;}/***************************************************************************** Function : get_host_and_path** Parameters :* IN char *ctrl_url : URL * OUT memptr *host : host string* OUT memptr *path : path string* OUT uri_type* url : URL type** Description : This function retrives the host and path from the * control URL** Return : int* returns 0 on sucess; -1 on error** Note :****************************************************************************/static XINLINE intget_host_and_path( IN char *ctrl_url, OUT memptr * host, OUT memptr * path, OUT uri_type * url ){ if( parse_uri( ctrl_url, strlen( ctrl_url ), url ) != HTTP_SUCCESS ) { return -1; } host->buf = url->hostport.text.buff; host->length = url->hostport.text.size; path->buf = url->pathquery.buff; path->length = url->pathquery.size; return 0;}/***************************************************************************** Function : get_action_name** Parameters :* IN char* action : string containing action name* OUT memptr* name : name of the action ** Description : This functions retirves the action name in the buffer** Return : int* returns 0 on success; -1 on error** Note :****************************************************************************/static XINLINE intget_action_name( IN char *action, OUT memptr * name ){ memptr dummy; int ret_code; ret_code = matchstr( action, strlen( action ), " <%s:%s", &dummy, name ); return ret_code == PARSE_OK ? 0 : -1;}/***************************************************************************** Function : add_man_header** Parameters :* INOUT membuffer* headers : HTTP header** Description : This function adds "MAN" field in the HTTP header** Return : int* returns 0 on success; UPNP_E_OUTOFMEMORY on error** Note :****************************************************************************/static XINLINE intadd_man_header( INOUT membuffer * headers ){ char *soap_action_hdr; char *man_hdr = "MAN: \"http://schemas.xmlsoap.org/soap/envelope/\"; " "ns=01\r\n01-"; // change POST to M-POST if( membuffer_insert( headers, "M-", 2, 0 ) != 0 ) { return UPNP_E_OUTOF_MEMORY; } soap_action_hdr = strstr( headers->buf, "SOAPACTION:" ); assert( soap_action_hdr != NULL ); // can't fail // insert MAN header if( membuffer_insert( headers, man_hdr, strlen( man_hdr ), soap_action_hdr - headers->buf ) != 0 ) { return UPNP_E_OUTOF_MEMORY; } return 0;}/***************************************************************************** Function : soap_request_and_response** Parameters :* IN membuffer* request : request that will be sent to the device* IN uri_type* destination_url : destination address string* OUT http_parser_t *response : response from the device** Description : This function sends the control point's request to the * device and receives a response from it.** Return : int** Note :****************************************************************************/static intsoap_request_and_response( IN membuffer * request, IN uri_type * destination_url, OUT http_parser_t * response ){ int ret_code; ret_code = http_RequestAndResponse( destination_url, request->buf, request->length, SOAPMETHOD_POST, UPNP_TIMEOUT, response ); if( ret_code != 0 ) { httpmsg_destroy( &response->msg ); return ret_code; } // method-not-allowed error if( response->msg.status_code == HTTP_METHOD_NOT_ALLOWED ) { ret_code = add_man_header( request ); // change to M-POST msg if( ret_code != 0 ) { return ret_code; } httpmsg_destroy( &response->msg ); // about to reuse response // try again ret_code = http_RequestAndResponse( destination_url, request->buf, HTTPMETHOD_MPOST, request->length, UPNP_TIMEOUT, response ); if( ret_code != 0 ) { httpmsg_destroy( &response->msg ); } } return ret_code;}/***************************************************************************** Function : get_response_value** Parameters :* IN http_message_t* hmsg : HTTP response message* IN int code : return code in the HTTP response* IN char*name : name of the action* OUT int *upnp_error_code : UPnP error code* OUT IXML_Node ** action_value : SOAP response node * OUT DOMString * str_value : state varible value ( in the case of * querry state variable request) ** Description : This function handles the response coming back from the * device. This function parses the response and gives back the SOAP * response node.** Return : int* return the type of the SOAP message if successful else returns * appropriate error.** Note :****************************************************************************/static intget_response_value( IN http_message_t * hmsg, IN int code, IN char *name, OUT int *upnp_error_code, OUT IXML_Node ** action_value, OUT DOMString * str_value ){ IXML_Node *node = NULL; IXML_Node *root_node = NULL; IXML_Node *error_node = NULL; IXML_Document *doc = NULL; char *node_str = NULL; char *temp_str = NULL; DOMString error_node_str = NULL; int err_code; xboolean done = FALSE; char *names[5]; DOMString nodeValue; err_code = UPNP_E_BAD_RESPONSE; // default error // only 200 and 500 status codes are relevant if( ( hmsg->status_code != HTTP_OK && hmsg->status_code != HTTP_INTERNAL_SERVER_ERROR ) || !has_xml_content_type( hmsg ) ) { goto error_handler; } if( ixmlParseBufferEx( hmsg->entity.buf, &doc ) != IXML_SUCCESS ) { goto error_handler; } root_node = ixmlNode_getFirstChild( ( IXML_Node * ) doc ); if( root_node == NULL ) { goto error_handler; } if( code == SOAP_ACTION_RESP ) { // // try reading soap action response // assert( action_value != NULL ); *action_value = NULL; names[0] = "Envelope"; names[1] = "Body"; names[2] = name; if( dom_find_deep_node( names, 3, root_node, &node ) == UPNP_E_SUCCESS ) { node_str = ixmlPrintDocument( node ); if( node_str == NULL ) { err_code = UPNP_E_OUTOF_MEMORY; goto error_handler; } if( ixmlParseBufferEx( node_str, ( IXML_Document ** ) action_value ) != IXML_SUCCESS ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -