469 lines
12 KiB
C
469 lines
12 KiB
C
/*
|
|
* Copyright (C) 2009 Mamadou Diop.
|
|
*
|
|
* Contact: Mamadou Diop <diopmamadou@yahoo.fr>
|
|
*
|
|
* 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with DOUBANGO.
|
|
*
|
|
*/
|
|
|
|
/**@file txc_rls.c
|
|
* @brief RFC 4826 subclause 4: <a href="http://tools.ietf.org/html/rfc4826#section-4">RLS Services Documents</a>
|
|
*
|
|
* @author Mamadou Diop <diopmamadou(at)yahoo.fr>
|
|
*
|
|
* @date Created: Sat Nov 8 16:54:58 2009 mdiop
|
|
*/
|
|
|
|
#include "txc_rls.h"
|
|
#include "txc_macros.h"
|
|
#include "txc.h"
|
|
|
|
#include "tsk_memory.h"
|
|
#include "tsk_string.h"
|
|
#include "tsk_macros.h"
|
|
|
|
#include <string.h>
|
|
|
|
/**@defgroup txc_rls_group XCAP RLS Services Documents
|
|
*/
|
|
|
|
|
|
/**@page txc_rls_page XCAP RLS Services Documents Tutorial (rls-services)
|
|
* @par Application Unique ID (AUID)
|
|
* - '<span style="text-decoration:underline;">rls-services</span>' as per rfc 4826 subclause 4.4.1
|
|
* @par Default Document Namespace
|
|
* - '<span style="text-decoration:underline;">urn:ietf:params:xml:ns:rls-services</span>' as per rfc 4826 subclause 4.4.4
|
|
* @par MIME Type
|
|
* - '<span style="text-decoration:underline;">application/rls-services+xml</span>' as per rfc 4826 subclause 4.4.2
|
|
* @par Default document name
|
|
* - '<span style="text-decoration:underline;">index</span>' as per rfc 4826 subclause 4.4.7
|
|
*
|
|
* <H2>== Deserialize and dump an rls-services document received from an XDMS==</H2>
|
|
* @code
|
|
#include "txc_api.h"
|
|
|
|
txc_rls_t* rls = 0;
|
|
tsk_list_item_t* item = 0;
|
|
tsk_list_t *list = 0;
|
|
printf("\n---\nTEST RLS-SERVICES\n---\n");
|
|
{
|
|
// create rls context
|
|
rls = txc_rls_create(buffer, size);
|
|
|
|
// get all services
|
|
list = txc_rls_get_all_services(rls);
|
|
|
|
// dump services
|
|
tsk_list_foreach(item, list)
|
|
{
|
|
txc_rls_service_t *rls_service = ((txc_rls_service_t*)item->data);
|
|
char* rls_service_str = txc_rls_service_serialize(rls_service);
|
|
printf("\n%s\n", rls_service_str);
|
|
TSK_FREE(rls_service_str);
|
|
}
|
|
|
|
// free services
|
|
TSK_LIST_SAFE_FREE(list);
|
|
|
|
// free rls context
|
|
txc_rls_free(&rls);
|
|
}
|
|
* @endcode
|
|
*/
|
|
|
|
#define RLS_RETURN_IF_INVALID(rls) if(!rls || !(rls->docPtr)) return 0;
|
|
|
|
#define RLS_XML_HEADER "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \
|
|
"<rls-services xmlns=\""TXC_NS_RLS"\">"
|
|
#define RLS_XML_FOOTER "</rls-services>"
|
|
|
|
///**@ingroup txc_rls_group
|
|
//* Internal function to initialize a service .
|
|
//* You MUST call @ref TXC_RLS_SERVICE_CREATE to create and initialize your object.
|
|
//* @param service The service element to initialize
|
|
//*/
|
|
//void txc_rls_service_init(txc_rls_service_t *service)
|
|
//{
|
|
//}
|
|
|
|
|
|
/**@ingroup txc_rls_group
|
|
* Update an rls service.
|
|
* @param service The service to update
|
|
* @param uri The new uri.
|
|
* @param resource_list The new resource-list
|
|
*/
|
|
void txc_rls_service_set(txc_rls_service_t *service, const char* uri, const char* resource_list)
|
|
{
|
|
if(service)
|
|
{
|
|
tsk_strupdate(&(service->uri), uri);
|
|
tsk_strupdate(&(service->resource_list), resource_list);
|
|
}
|
|
}
|
|
|
|
/**@ingroup txc_rls_group
|
|
* Add a new package to a service
|
|
* @param service The service to update
|
|
* @param package The new package to add to the service
|
|
*/
|
|
void txc_rls_service_add_package(txc_rls_service_t *service, const char* package)
|
|
{
|
|
tsk_list_item_t *item = 0;
|
|
if(service)
|
|
{
|
|
if(!(service->packages))
|
|
{
|
|
service->packages = TSK_LIST_CREATE();
|
|
}
|
|
|
|
item = TSK_LIST_ITEM_CREATE();
|
|
item->data = TSK_STRING_CREATE(package);
|
|
tsk_list_add_item(service->packages, &item);
|
|
}
|
|
}
|
|
|
|
///**@ingroup txc_rls_group
|
|
//* Internal function to free an rls service previously created using @ref TXC_RLS_SERVICE_CREATE.
|
|
//* You MUST call @ref TXC_RLS_SERVICE_SAFE_FREE to free a service.
|
|
//* @param _service The service to free.
|
|
//* @sa @ref TXC_RLS_SERVICE_SAFE_FREE
|
|
//*/
|
|
//void txc_rls_service_free(void **_service)
|
|
//{
|
|
// txc_rls_service_t **service = ((txc_rls_service_t**)_service);
|
|
//
|
|
// TSK_FREE((*service)->uri);
|
|
// TSK_FREE((*service)->resource_list);
|
|
// TSK_LIST_SAFE_FREE((*service)->packages);
|
|
//
|
|
// tsk_free2(_service);
|
|
//}
|
|
|
|
/**@ingroup txc_rls_group
|
|
* Internal function to deserialize an rls service from an XML document.
|
|
* @param node The pointer to the XML node from which to deserialize the rls service
|
|
* @retval Pointer to a @ref txc_rls_service_t object or NULL if deserialization fail.
|
|
* You MUST call @ref TXC_RLS_SERVICE_SAFE_FREE to free the returned object.
|
|
*/
|
|
txc_rls_service_t* txc_rls_service_from_xml(const xmlNodePtr node)
|
|
{
|
|
xmlNodePtr node2 = 0;
|
|
txc_rls_service_t *rls_service = 0;
|
|
tsk_list_item_t* item = 0;
|
|
|
|
if(tsk_xml_find_node(node, "service", nft_none))
|
|
{
|
|
rls_service = TXC_RLS_SERVICE_CREATE();
|
|
|
|
/* uri */
|
|
node2 = tsk_xml_select_node(node,
|
|
TSK_XML_NODE_SELECT_ATT_VALUE("service", "uri"),
|
|
TSK_XML_NODE_SELECT_END());
|
|
rls_service->uri = tsk_strdup(TSK_XML_NODE_SAFE_GET_TEXTVALUE(node2));
|
|
|
|
/* resource-list */
|
|
node2 = tsk_xml_select_node(node, TSK_XML_NODE_SELECT_BY_NAME("service"),
|
|
TSK_XML_NODE_SELECT_BY_NAME("resource-list"),
|
|
TSK_XML_NODE_SELECT_END());
|
|
rls_service->resource_list = tsk_strdup(TSK_XML_NODE_SAFE_GET_TEXTVALUE(node2));
|
|
|
|
/* packages */
|
|
node2 = tsk_xml_select_node(node, TSK_XML_NODE_SELECT_BY_NAME("service"),
|
|
TSK_XML_NODE_SELECT_BY_NAME("packages"),
|
|
TSK_XML_NODE_SELECT_CONTENT(),
|
|
TSK_XML_NODE_SELECT_END());
|
|
/* select first package */
|
|
if(!tsk_xml_find_node(node2, "package", nft_none)) node2 = tsk_xml_find_node(node2, "package", nft_next);
|
|
if(node2)
|
|
{
|
|
rls_service->packages = TSK_LIST_CREATE();
|
|
do
|
|
{
|
|
item = TSK_LIST_ITEM_CREATE();
|
|
item->data = TSK_STRING_CREATE(TSK_XML_NODE_SAFE_GET_TEXTVALUE(node2->children));
|
|
tsk_list_add_item(rls_service->packages, &item);
|
|
}
|
|
while(node2 = tsk_xml_find_node(node2, "service", nft_next));
|
|
}
|
|
}else return 0;
|
|
|
|
return rls_service;
|
|
}
|
|
|
|
///**@ingroup txc_rls_group
|
|
//* Create a rls context from an XML buffer.
|
|
//* @param buffer The XML buffer from which to create the rls context
|
|
//* @param size The size of the XML buffer
|
|
//* @retval Pointer to a @ref txc_rls_t object or NULL. You MUST call @ref txc_rls_free to free the returned object.
|
|
//* @sa @ref txc_rls_free
|
|
//*/
|
|
//txc_rls_t* txc_rls_create(const char* buffer, size_t size)
|
|
//{
|
|
// if(buffer && size)
|
|
// {
|
|
// txc_rls_t* rls = (txc_rls_t*)tsk_calloc2(1, sizeof(txc_rls_t));
|
|
// rls->docPtr = xmlParseMemory(buffer, (int)size);
|
|
//
|
|
// return rls;
|
|
// }
|
|
//
|
|
// return 0;
|
|
//}
|
|
|
|
/**@ingroup txc_rls_group
|
|
* Get all rls services
|
|
* @param rls The rls context from which to extract the services
|
|
* @retval Pointer to a @ref txc_rls_service_L_t object or NULL. You must call @a TSK_LIST_SAFE_FREE to free the returned object.
|
|
*/
|
|
txc_rls_service_L_t* txc_rls_get_all_services(const txc_rls_t* rls)
|
|
{
|
|
txc_rls_service_t* rls_service = 0;
|
|
txc_rls_service_L_t* list = 0;
|
|
xmlNodePtr node = 0;
|
|
|
|
RLS_RETURN_IF_INVALID(rls);
|
|
|
|
/* root */
|
|
node = tsk_xml_select_node(rls->docPtr->children,
|
|
TSK_XML_NODE_SELECT_BY_NAME("rls-services"),
|
|
TSK_XML_NODE_SELECT_END());
|
|
|
|
/* select first service */
|
|
if(!tsk_xml_find_node(node, "service", nft_none)) node = tsk_xml_find_node(node, "service", nft_next);
|
|
if(node)
|
|
{
|
|
list = TSK_LIST_CREATE();
|
|
do
|
|
{
|
|
rls_service = txc_rls_service_from_xml(node);
|
|
tsk_list_add_data(list, ((void**) &rls_service));
|
|
}
|
|
while(node = tsk_xml_find_node(node, "service", nft_next));
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/**@ingroup txc_rls_group
|
|
* Serialize an rls service
|
|
* @param service The service to serialize
|
|
* @retval XML string representing the rls service. You MUST call @a TSK_FREE to free the returned string.
|
|
*/
|
|
char* txc_rls_service_serialize(const txc_rls_service_t *service)
|
|
{
|
|
char* service_str = 0;
|
|
char* package_str = 0;
|
|
tsk_list_item_t* item = 0;
|
|
|
|
if(!service) return 0;
|
|
|
|
/* packages */
|
|
tsk_list_foreach(item, service->packages)
|
|
{
|
|
char* curr = 0;
|
|
tsk_sprintf(&curr, "<package>%s</package>", TSK_STRING_STR(item->data));
|
|
tsk_strcat(&package_str, curr);
|
|
TSK_FREE(curr);
|
|
}
|
|
/* service */
|
|
tsk_sprintf(&service_str,
|
|
"<service uri=\"%s\">"
|
|
"<resource-list>%s</resource-list>"
|
|
"<packages>"
|
|
"%s"
|
|
"</packages>"
|
|
"</service>",
|
|
service->uri, service->resource_list, package_str);
|
|
TSK_FREE(package_str);
|
|
return service_str;
|
|
}
|
|
|
|
/**@ingroup txc_rls_group
|
|
* Serialize a list of several rls services
|
|
* @param services The list of rls services to serialize
|
|
* @retval XML string representing the list rls services. You MUST call @a TSK_FREE to free the returned string.
|
|
*/
|
|
char* txc_rls_services_serialize(const tsk_list_t *services)
|
|
{
|
|
tsk_list_item_t* item = 0;
|
|
char* services_str = 0;
|
|
|
|
if(!services) return 0;
|
|
|
|
/* xml header */
|
|
tsk_strcat(&services_str, RLS_XML_HEADER);
|
|
|
|
tsk_list_foreach(item, services)
|
|
{
|
|
/* get service */
|
|
txc_rls_service_t *service = ((txc_rls_service_t*)item->data);
|
|
char* service_str = txc_rls_service_serialize(service);
|
|
tsk_strcat(&services_str, service_str);
|
|
TSK_FREE(service_str);
|
|
}
|
|
|
|
/* xml footer */
|
|
tsk_strcat(&services_str, RLS_XML_FOOTER);
|
|
|
|
return services_str;
|
|
}
|
|
|
|
///**@ingroup txc_rls_group
|
|
//* Internal function to free an rls context previously created using @ref txc_rls_create.
|
|
//* @param rls The context to free
|
|
//* @sa @ref txc_rls_create
|
|
//*/
|
|
//void txc_rls_free(txc_rls_t **rls)
|
|
//{
|
|
// if(*rls)
|
|
// {
|
|
// xmlFreeDoc((*rls)->docPtr);
|
|
//
|
|
// tsk_free2(rls);
|
|
// }
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================
|
|
// RLS object definition
|
|
//
|
|
|
|
/**@ingroup txc_rls_group
|
|
*/
|
|
static void* txc_rls_create(void *self, va_list * app)
|
|
{
|
|
txc_rls_t *rls = self;
|
|
if(rls)
|
|
{
|
|
const char* buffer = va_arg(*app, const char*);
|
|
size_t size = va_arg(*app, size_t);
|
|
if(buffer && size)
|
|
{
|
|
rls->docPtr = xmlParseMemory(buffer, (int)size);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TSK_DEBUG_ERROR("Failed to create new rls object.");
|
|
}
|
|
return self;
|
|
}
|
|
|
|
/**@ingroup txc_rls_group
|
|
*/
|
|
static void* txc_rls_destroy(void * self)
|
|
{
|
|
txc_rls_t *rls = self;
|
|
if(rls)
|
|
{
|
|
xmlFreeDoc(rls->docPtr);
|
|
}
|
|
else
|
|
{
|
|
TSK_DEBUG_WARN("Cannot destroy NULL rls object.");
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
static const tsk_object_def_t txc_rls_def_s =
|
|
{
|
|
sizeof(txc_rls_t),
|
|
txc_rls_create,
|
|
txc_rls_destroy,
|
|
0
|
|
};
|
|
const void *txc_rls_def_t = &txc_rls_def_s;
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================
|
|
// RLS service definition
|
|
//
|
|
|
|
/**@ingroup txc_rls_group
|
|
*/
|
|
static void* txc_rls_service_create(void *self, va_list * app)
|
|
{
|
|
txc_rls_service_t *rls_service = self;
|
|
if(!rls_service)
|
|
{
|
|
TSK_DEBUG_ERROR("Failed to create new rls service object.");
|
|
}
|
|
return self;
|
|
}
|
|
|
|
/**@ingroup txc_rls_group
|
|
*/
|
|
static void* txc_rls_service_destroy(void * self)
|
|
{
|
|
txc_rls_service_t *rls_service = self;
|
|
if(rls_service)
|
|
{
|
|
TSK_FREE(rls_service->uri);
|
|
TSK_FREE(rls_service->resource_list);
|
|
TSK_LIST_SAFE_FREE(rls_service->packages);
|
|
}
|
|
else
|
|
{
|
|
TSK_DEBUG_WARN("Cannot destroy NULL rls service object.");
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
static const tsk_object_def_t txc_rls_service_def_s =
|
|
{
|
|
sizeof(txc_rls_service_t),
|
|
txc_rls_service_create,
|
|
txc_rls_service_destroy,
|
|
0
|
|
};
|
|
const void *txc_rls_service_def_t = &txc_rls_service_def_s;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#undef RLS_RETURN_IF_INVALID
|
|
|
|
#undef RLS_XML_HEADER
|
|
#undef RLS_XML_FOOTER |