doubango/tinyXCAP/src/txcap_action.c
c732d49e
 #if HAVE_CRT
 #define _CRTDBG_MAP_ALLOC 
 #include <stdlib.h> 
 #include <crtdbg.h>
 #endif //HAVE_CRT
 /*
74ca6d11
 * Copyright (C) 2020, University of the Basque Country (UPV/EHU)
c732d49e
 * Contact for licensing options: <licensing-mcpttclient(at)mcopenplatform(dot)com>
 *
 * The original file was part of Open Source Doubango Framework
 * Copyright (C) 2010-2011 Mamadou Diop.
 * Copyright (C) 2012 Doubango Telecom <http://doubango.org>
 *
 * This file is part of Open Source Doubango Framework.
 *
 * DOUBANGO is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DOUBANGO is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DOUBANGO.
 *
 */
 /**@file txcap_action.c
  * @brief XCAP actions.
  *
  * @author Mamadou Diop <diopmamadou(at)doubango.org>
  *
 
  */
 #include "tinyxcap/txcap_action.h"
 
 #include "tsk_options.h"
 #include "tsk_params.h"
 #include "tinyxcap/txcap_selector.h"
 
 /**@defgroup txcap_action_group XDMC (Sending Requests)
 */
 
 extern char* __txcap_selector_get_url(const txcap_stack_handle_t* stack, const char* auid_id, va_list* app);
 extern char* __txcap_selector_get_url_no_auid(const txcap_stack_handle_t* stack, const char* auid_id, va_list* app);
 
 
 /** Sends HTTP/HTTPS request to the XDMS.
 */
 int txcap_action_perform(txcap_stack_handle_t* stack, txcap_action_type_t type, txcap_action_target_t target, ...)
 {
 	tsk_options_L_t* options = tsk_null;
 	tsk_params_L_t* headers = tsk_null;
 	char* urlstring = tsk_null;
 	thttp_action_t* action;
 	thttp_dialog_t* dialog;
 	int ret = -1;
 	txcap_action_param_type_t curr;
 	const char* method = "GET";
 	const char* mime_type = tsk_null;
 	const char* AUID_STR = tsk_null;
 	const void* PAY_PTR = tsk_null;
 	size_t PAY_SIZE = 0;
 	va_list ap;
 	txcap_stack_t* xcap_stack = stack;
 
 	if(!xcap_stack){
 		goto bail;
 	}
 	else{
 		xcap_stack = tsk_object_ref(stack);
 		options = tsk_list_create();
 		headers = tsk_list_create();
 	}
 
 	va_start(ap, target);
 	while((curr = va_arg(ap, txcap_action_param_type_t)) != txcap_apt_null){
 		switch(curr){
 			case txcap_apt_option:
 				{	/*(thttp_action_option_t)ID_INT, (const char*)VALUE_STR*/
 					thttp_action_option_t ID_INT = va_arg(ap, thttp_action_option_t);
 					const char* VALUE_STR = va_arg(ap, const char *);
 					tsk_options_add_option(&options, ID_INT, VALUE_STR);
 					break;
 				}
 			case txcap_apt_header:
 				{	/* (const char*)NAME_STR, (const char*)VALUE_STR */
 					const char* NAME_STR = va_arg(ap, const char *);
 					const char* VALUE_STR = va_arg(ap, const char *);
 					if(VALUE_STR == (const char*)-1){
 						tsk_params_remove_param(headers, NAME_STR);
 					}
 					else{
 						tsk_params_add_param(&headers, NAME_STR, VALUE_STR);
 					}
 					break;
 				}
 			case txcap_apt_payload:
 				{	/*(const void*)PAY_PTR, (size_t)PAY_SIZE*/
 					PAY_PTR = va_arg(ap, const void *);
 					PAY_SIZE = va_arg(ap, size_t);
 					break;
 				}
 			case txcap_apt_selector:
 				{	/*(const char*)AUID_STR, __VA_ARGS__*/
 					AUID_STR = va_arg(ap, const char *);
 					if(!urlstring){
 						urlstring = __txcap_selector_get_url(stack, AUID_STR, &ap);
 					}
 					break;
 				}
 			case txcap_apt_selector_no_auid:
 				{	/*(const char*)AUID_STR, __VA_ARGS__*/
 					AUID_STR = va_arg(ap, const char *);
 					if(!urlstring){
 						urlstring = __txcap_selector_get_url_no_auid(stack, AUID_STR, &ap);
 					}
 					break;
 				}
 			case txcap_apt_urlstring:
 				{	/* (const char*)URI_STR */
 					const char* URI_STR = va_arg(ap, const char *);
 					if(!urlstring){
 						urlstring = tsk_strdup(URI_STR);
 					}
 					break;
 				}
 			
 			default:
 				{
 					TSK_DEBUG_ERROR("NOT SUPPORTED.");
 					goto done;
 				}
 		}/* switch */
 	} /* while */
 
 done:
 	va_end(ap);
 
 	/* checks urlstring */
 	if(!urlstring){
 		TSK_DEBUG_ERROR("Failed to compute XCAP URL");
 		goto bail;
 	}
 
 	/* HTTP method */
 	switch(type){
 		case txcap_atp_create:
 		case txcap_atp_replace:
 			method = "PUT"; break;
 		case txcap_atp_fetch:
 			method = "GET"; break;
 		case txcap_atp_delete:
 			method = "DELETE"; break;
 	}
 
 	/*content-type*/
 	switch(target){
 		case txcap_atg_element:
 			mime_type = TXCAP_MIME_TYPE_ELEMENT; break;
 		case txcap_atg_document:
 			{
 				if(AUID_STR){
 					txcap_auid_t* auid;
 					if((auid = txcap_auid_get_by_id(xcap_stack->auids, AUID_STR))){
 						mime_type = (const char*)auid->mime_type; // (cont char*) do not strdup()
 						TSK_OBJECT_SAFE_FREE(auid);
 					}
 					else{
 						TSK_DEBUG_WARN("Failed to find auid with id=%s", AUID_STR);
 					}
 				}
 				break;
 			}
 		case txcap_atg_attribute:
 			mime_type = TXCAP_MIME_TYPE_ATTRIBUTE; break;
 	}
 
 	/* HTTP action */
 	if((action = thttp_action_create(thttp_atype_o_request, urlstring, method, tsk_null))){
 		const tsk_list_item_t* item;
 		if((dialog = thttp_dialog_new(xcap_stack->http_session))){
 			/* copy options */
 			tsk_list_foreach(item, options){
 				tsk_options_add_option(&action->options, ((const tsk_option_t*)item->data)->id, ((const tsk_option_t*)item->data)->value);
 			}
 			/* copy action-level headers */
 			tsk_list_foreach(item, headers){
 				tsk_params_add_param(&action->headers, ((const tsk_param_t*)item->data)->name, ((const tsk_param_t*)item->data)->value);
 			}
 			/* copy session-level headers ==> will be added by thttp_dialog_send_request()*/
 			//--tsk_list_pushback_list(action->headers, ((thttp_session_t*)xcap_stack->http_session)->headers);
 
 			/* Content-Type */
 			if(mime_type){
 				if(!tsk_params_have_param(action->headers, "Content-Type")){
 					tsk_params_add_param(&action->headers, "Content-Type", mime_type);
 				}
 			}
 
 			/* payload */
 			if(PAY_PTR && PAY_SIZE){
 				action->payload = tsk_buffer_create(PAY_PTR, PAY_SIZE);
 			}
 			
 			/* performs */
 			ret = thttp_dialog_fsm_act(dialog, action->type, tsk_null, action);
 			tsk_object_unref(dialog);
 		}
 		else{
 			TSK_DEBUG_ERROR("Failed to create new HTTP/HTTPS dialog.");
 			ret = -2;
 		}
 		TSK_OBJECT_SAFE_FREE(action);
 	}
 
 bail:
 	TSK_FREE(urlstring);
 	TSK_OBJECT_SAFE_FREE(options);
 	TSK_OBJECT_SAFE_FREE(headers);
 	tsk_object_unref(xcap_stack);
 	return ret;
 }