⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 soap_device.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 3 页
字号:
///////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////

#ifdef INCLUDE_DEVICE_APIS
#if EXCLUDE_SOAP == 0

#define SOAP_BODY "Body"
#define SOAP_URN "http://schemas.xmlsoap.org/soap/envelope/"

#define QUERY_STATE_VAR_URN "urn:schemas-upnp-org:control-1-0"

#include "config.h"
#include "upnpapi.h"
#include "parsetools.h"
#include "statcodes.h"
#include "httpparser.h"
#include "httpreadwrite.h"
#include "unixutil.h"

// timeout duration in secs for transmission/reception
#define SOAP_TIMEOUT UPNP_TIMEOUT

#define SREQ_HDR_NOT_FOUND	 -1
#define SREQ_BAD_HDR_FORMAT	 -2

#define SOAP_INVALID_ACTION 401
#define SOAP_INVALID_ARGS	402
#define SOAP_OUT_OF_SYNC	403
#define SOAP_INVALID_VAR	404
#define SOAP_ACTION_FAILED	501

static const char *Soap_Invalid_Action = "Invalid Action";

//static const char* Soap_Invalid_Args = "Invalid Args";
static const char *Soap_Action_Failed = "Action Failed";
static const char *Soap_Invalid_Var = "Invalid Var";

const char *ContentTypeHeader =
    "CONTENT-TYPE: text/xml; charset=\"utf-8\"\n";

/****************************************************************************
*	Function :	get_request_type
*
*	Parameters :
*			IN http_message_t* request :	HTTP request
*			OUT memptr* action_name :	SOAP action name
*
*	Description :	This function retrives the name of the SOAP action
*
*	Return : int
*		0 if successful else returns appropriate error.
*	Note :
****************************************************************************/
static XINLINE int
get_request_type( IN http_message_t * request,
                  OUT memptr * action_name )
{
    memptr value;
    memptr ns_value,
      dummy_quote;
    http_header_t *hdr;
    char save_char;
    char *s;
    membuffer soap_action_name;

    // find soapaction header
    //
    if( request->method == SOAPMETHOD_POST ) {
        if( httpmsg_find_hdr( request, HDR_SOAPACTION, &value )
            == NULL ) {
            return SREQ_HDR_NOT_FOUND;
        }
    } else                      // M-POST
    {
        // get NS value from MAN header
        hdr = httpmsg_find_hdr( request, HDR_MAN, &value );
        if( hdr == NULL ) {
            return SREQ_HDR_NOT_FOUND;
        }

        if( matchstr( value.buf, value.length, "%q%i ; ns = %s",
                      &dummy_quote, &ns_value ) != 0 ) {
            return SREQ_BAD_HDR_FORMAT;
        }
        // create soapaction name header
        membuffer_init( &soap_action_name );
        if( ( membuffer_assign( &soap_action_name,
                                ns_value.buf, ns_value.length )
              == UPNP_E_OUTOF_MEMORY ) ||
            ( membuffer_append_str( &soap_action_name,
                                    "-SOAPACTION" ) ==
              UPNP_E_OUTOF_MEMORY )
             ) {
            membuffer_destroy( &soap_action_name );
            return UPNP_E_OUTOF_MEMORY;
        }

        hdr = httpmsg_find_hdr_str( request, soap_action_name.buf );
        membuffer_destroy( &soap_action_name );
        if( hdr == NULL ) {
            return SREQ_HDR_NOT_FOUND;
        }

        value.buf = hdr->value.buf;
        value.length = hdr->value.length;
    }

    // determine type
    //
    save_char = value.buf[value.length];
    value.buf[value.length] = '\0';

    s = strchr( value.buf, '#' );
    if( s == NULL ) {
        value.buf[value.length] = save_char;
        return SREQ_BAD_HDR_FORMAT;
    }

    s++;                        // move to value

    if( matchstr( s, value.length - ( s - value.buf ), "%s",
                  action_name ) != PARSE_OK ) {
        value.buf[value.length] = save_char;
        return SREQ_BAD_HDR_FORMAT;
    }
    // action name or variable ?
    if( memptr_cmp( action_name, "QueryStateVariable" ) == 0 ) {
        // query variable
        action_name->buf = NULL;
        action_name->length = 0;
    }

    value.buf[value.length] = save_char;    // restore
    return 0;
}

/****************************************************************************
*	Function :	send_error_response
*
*	Parameters :
*			IN SOCKINFO *info :	socket info
*			IN int error_code :	error code
*			IN const char* err_msg :	error message
*			IN http_message_t* hmsg :	HTTP request
*
*	Description :	This function sends SOAP error response
*
*	Return : void
*
*	Note :
****************************************************************************/
static void
send_error_response( IN SOCKINFO * info,
                     IN int error_code,
                     IN const char *err_msg,
                     IN http_message_t * hmsg )
{
    int content_length;
    int timeout_secs = SOAP_TIMEOUT;
    int major,
      minor;
    const char *start_body =
        "<s:Envelope\n"
        "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
        "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
        "<s:Body>\n"
        "<s:Fault>\n"
        "<faultcode>s:Client</faultcode>\n"
        "<faultstring>UPnPError</faultstring>\n"
        "<detail>\n"
        "<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n"
        "<errorCode>";

    const char *mid_body = "</errorCode>\n" "<errorDescription>";

    const char *end_body =
        "</errorDescription>\n"
        "</UPnPError>\n"
        "</detail>\n" "</s:Fault>\n" "</s:Body>\n" "</s:Envelope>\n";

    char err_code_str[30];

    membuffer headers;

    sprintf( err_code_str, "%d", error_code );

    // calc body len
    content_length = strlen( start_body ) + strlen( err_code_str ) +
        strlen( mid_body ) + strlen( err_msg ) + strlen( end_body );

    http_CalcResponseVersion( hmsg->major_version, hmsg->minor_version,
                              &major, &minor );

    // make headers
    membuffer_init( &headers );
    if( http_MakeMessage( &headers, major, minor,
                          "RNsDsSc" "sssss",
                          500,
                          content_length,
                          ContentTypeHeader,
                          "EXT:\r\n",
                          start_body, err_code_str, mid_body, err_msg,
                          end_body ) != 0 ) {
        membuffer_destroy( &headers );
        return;                 // out of mem
    }
    // send err msg
    http_SendMessage( info, &timeout_secs, "b",
                      headers.buf, headers.length );

    membuffer_destroy( &headers );
}

/****************************************************************************
*	Function :	send_var_query_response
*
*	Parameters :
*			IN SOCKINFO *info :	socket info
*			IN const char* var_value :	value of the state variable
*			IN http_message_t* hmsg :	HTTP request
*
*	Description :	This function sends response of get var status
*
*	Return : void
*
*	Note :
****************************************************************************/
static XINLINE void
send_var_query_response( IN SOCKINFO * info,
                         IN const char *var_value,
                         IN http_message_t * hmsg )
{
    int content_length;
    int timeout_secs = SOAP_TIMEOUT;
    int major,
      minor;
    const char *start_body =
        "<s:Envelope\n"
        "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
        "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
        "<s:Body>\n"
        "<u:QueryStateVariableResponse "
        "xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\n" "<return>";

    const char *end_body =
        "</return>\n"
        "</u:QueryStateVariableResponse>\n"
        "</s:Body>\n" "</s:Envelope>\n";

    membuffer response;

    http_CalcResponseVersion( hmsg->major_version, hmsg->minor_version,
                              &major, &minor );

    content_length = strlen( start_body ) + strlen( var_value ) +
        strlen( end_body );

    // make headers
    membuffer_init( &response );
    if( http_MakeMessage( &response, major, minor,
                          "RNsDsSc" "sss",
                          HTTP_OK,
                          content_length,
                          ContentTypeHeader,
                          "EXT:\r\n",
                          start_body, var_value, end_body ) != 0 ) {
        membuffer_destroy( &response );
        return;                 // out of mem
    }
    // send msg
    http_SendMessage( info, &timeout_secs, "b",
                      response.buf, response.length );

    membuffer_destroy( &response );
}

/****************************************************************************
*	Function :	get_action_node
*
*	Parameters :
*		IN IXML_Document *TempDoc :	The root DOM node.
*		IN char *NodeName :	IXML_Node name to be searched.
*		OUT IXML_Document ** RespNode :	Response/Output node.
*
*	Description :	This function separates the action node from 
*	the root DOM node.
*
*	Return :	static XINLINE int
*		0 if successful, or -1 if fails.
*
*	Note :
****************************************************************************/
static XINLINE int
get_action_node( IN IXML_Document * TempDoc,
                 IN char *NodeName,
                 OUT IXML_Document ** RespNode )
{
    IXML_Node *EnvpNode = NULL;
    IXML_Node *BodyNode = NULL;
    IXML_Node *ActNode = NULL;
    DOMString ActNodeName = NULL;
    const DOMString nodeName;
    int ret_code = -1;          // error, by default
    IXML_NodeList *nl = NULL;

    DBGONLY( UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
                         "get_action_node(): node name =%s\n ", NodeName );
         )

        * RespNode = NULL;

    // Got the Envelope node here
    EnvpNode = ixmlNode_getFirstChild( ( IXML_Node * ) TempDoc );
    if( EnvpNode == NULL ) {
        goto error_handler;
    }

    nl = ixmlElement_getElementsByTagNameNS( ( IXML_Element * ) EnvpNode,
                                             "*", "Body" );

    if( nl == NULL ) {
        goto error_handler;
    }

    BodyNode = ixmlNodeList_item( nl, 0 );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -