/*! * \brief Searches for the node specifed by the last name in the 'name' array. * * \return UPNP_E_SUCCESS if successful, else returns appropriate error. */ static int dom_find_deep_node( /* [in] array of names. */ const char *names[], /* [in] size of array. */ int num_names, /* [in] Node from where it should should be searched. */ IXML_Node *start_node, /* [out] Node that matches the last name of the array. */ 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; } /* try again */ node = match_node; } /* this line not reached */ 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 int dom_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_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 int get_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; const char *temp_str = NULL; DOMString error_node_str = NULL; int err_code; xboolean done = FALSE; char *names[5]; const 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 = ixmlPrintNode( node ); if( node_str == NULL ) { err_code = UPNP_E_OUTOF_MEMORY; goto error_handler; } if( ixmlParseBufferEx( node_str, ( IXML_Document ** ) action_value ) != IXML_SUCCESS ) { err_code = UPNP_E_BAD_RESPONSE; goto error_handler; } err_code = SOAP_ACTION_RESP; done = TRUE; } } else if( code == SOAP_VAR_RESP ) { // try reading var response assert( str_value != NULL ); *str_value = NULL; names[0] = "Envelope"; names[1] = "Body"; names[2] = "QueryStateVariableResponse"; names[3] = "return"; if( dom_find_deep_node( names, 4, root_node, &node ) == UPNP_E_SUCCESS ) { nodeValue = get_node_value( node ); if( nodeValue == NULL ) { goto error_handler; } *str_value = ixmlCloneDOMString( nodeValue ); err_code = SOAP_VAR_RESP; done = TRUE; } } if( !done ) { // not action or var resp; read error code and description *str_value = NULL; names[0] = "Envelope"; names[1] = "Body"; names[2] = "Fault"; names[3] = "detail"; names[4] = "UPnPError"; if( dom_find_deep_node( names, 5, root_node, &error_node ) != UPNP_E_SUCCESS ) { goto error_handler; } if( dom_find_node( "errorCode", error_node, &node ) != UPNP_E_SUCCESS ) { goto error_handler; } temp_str = get_node_value( node ); if( temp_str == NULL ) { goto error_handler; } *upnp_error_code = atoi( temp_str ); if( *upnp_error_code > 400 ) { err_code = *upnp_error_code; goto error_handler; // bad SOAP error code } if( code == SOAP_VAR_RESP ) { if( dom_find_node( "errorDescription", error_node, &node ) != UPNP_E_SUCCESS ) { goto error_handler; } nodeValue = get_node_value( node ); if( nodeValue == NULL ) { goto error_handler; } *str_value = ixmlCloneDOMString( nodeValue ); if( *str_value == NULL ) { goto error_handler; } err_code = SOAP_VAR_RESP_ERROR; } else if( code == SOAP_ACTION_RESP ) { error_node_str = ixmlPrintNode( error_node ); if( error_node_str == NULL ) { err_code = UPNP_E_OUTOF_MEMORY; goto error_handler; } if( ixmlParseBufferEx( error_node_str, ( IXML_Document ** ) action_value ) != IXML_SUCCESS ) { err_code = UPNP_E_BAD_RESPONSE; goto error_handler; } err_code = SOAP_ACTION_RESP_ERROR; } } error_handler: ixmlDocument_free( doc ); ixmlFreeDOMString( node_str ); ixmlFreeDOMString( error_node_str ); return err_code; }