From a0dae0ad184ab4c605a69b1d68ef26272203e352 Mon Sep 17 00:00:00 2001 From: Cerghit Ionel Date: Wed, 5 Aug 2015 17:39:21 +0300 Subject: [PATCH 1/2] mi_xmlrpc_ng: fixed formatting and flushing problems in module --- modules/mi_xmlrpc_ng/http_fnc.c | 325 ++++++++++++++++++++++++-------- modules/mi_xmlrpc_ng/http_fnc.h | 13 +- 2 files changed, 253 insertions(+), 85 deletions(-) diff --git a/modules/mi_xmlrpc_ng/http_fnc.c b/modules/mi_xmlrpc_ng/http_fnc.c index 07c9d8f6e48..040179c147c 100644 --- a/modules/mi_xmlrpc_ng/http_fnc.c +++ b/modules/mi_xmlrpc_ng/http_fnc.c @@ -27,6 +27,7 @@ #include "../../str.h" #include "../../ut.h" +#include "../../strcommon.h" #include "../../mem/mem.h" #include "../../mem/shm_mem.h" #include "../../mi/mi.h" @@ -44,6 +45,8 @@ #define MI_XMLRPC_HTTP_XML_VALUE_NODE "value" #define MI_XMLRPC_HTTP_XML_STRING_NODE "string" + + extern str http_root; mi_xmlrpc_http_page_data_t html_page_data; @@ -223,12 +226,17 @@ do{ \ MI_XMLRPC_HTTP_COPY(p, (temp_holder)); \ }while(0) +static int mi_xmlrpc_http_recur_write_tree(char** pointer, char *buf, int max_page_len, + struct mi_node *tree, int level, unsigned int flags, int flush, struct mi_node *parent, int object_flags); +static int mi_xmlrpc_http_recur_write_node(char** pointer, char* buf, int max_page_len, + struct mi_node *node, int level, int dump_name, int flush); + static const str MI_XMLRPC_HTTP_CR = str_init("\n"); static const str MI_XMLRPC_HTTP_SLASH = str_init("/"); static const str MI_XMLRPC_HTTP_SEMICOLON = str_init(" : "); -static const str MI_XMLRPC_HTTP_NODE_INDENT = str_init("\t"); +static const str MI_XMLRPC_HTTP_NODE_INDENT = str_init(" "); static const str MI_XMLRPC_HTTP_NODE_SEPARATOR = str_init(":: "); static const str MI_XMLRPC_HTTP_ATTR_SEPARATOR = str_init(" "); static const str MI_XMLRPC_HTTP_ATTR_VAL_SEPARATOR = str_init("="); @@ -242,6 +250,25 @@ static const str MI_XMLRPC_HTTP_ESC_AMP = str_init("&"); /* & */ static const str MI_XMLRPC_HTTP_ESC_QUOT = str_init("""); /* " */ static const str MI_XMLRPC_HTTP_ESC_SQUOT = str_init("'"); /* ' */ +static const str MI_XMLRPC_HTTP_STRUCT_START = str_init(""); +static const str MI_XMLRPC_HTTP_STRUCT_END = str_init(""); +static const str MI_XMLRPC_HTTP_MEMBER_START = str_init(""); +static const str MI_XMLRPC_HTTP_MEMBER_END = str_init(""); +static const str MI_XMLRPC_HTTP_NAME_START = str_init(""); +static const str MI_XMLRPC_HTTP_NAME_END = str_init(""); +static const str MI_XMLRPC_HTTP_VALUE_START = str_init(""); +static const str MI_XMLRPC_HTTP_VALUE_END = str_init(""); + +static const str MI_XMLRPC_HTTP_VALUE_DEFAULT = str_init("value"); +static const str MI_XMLRPC_HTTP_NAME_DEFAULT = str_init("name"); +static const str MI_XMLRPC_HTTP_KIDS_DEFAULT = str_init("kids"); +static const str MI_XMLRPC_HTTP_ATTRIBUTES_DEFAULT = str_init("attributes"); + +static const str MI_XMLRPC_HTTP_ARRAY_START = str_init(""); +static const str MI_XMLRPC_HTTP_ARRAY_END = str_init(""); +static const str MI_XMLRPC_HTTP_DATA_START = str_init(""); +static const str MI_XMLRPC_HTTP_DATA_END = str_init(""); + int mi_xmlrpc_http_init_async_lock(void) { @@ -307,10 +334,6 @@ void mi_xmlrpc_http_destroy_async_lock(void) } } - -static int mi_xmlrpc_http_recur_flush_tree(char** pointer, char *buf, int max_page_len, - struct mi_node *tree, int level); - int mi_xmlrpc_http_flush_content(str *page, int max_page_len, struct mi_root* tree); @@ -322,6 +345,7 @@ int mi_xmlrpc_http_flush_tree(void* param, struct mi_root *tree) LM_CRIT("null param\n"); return 0; } + mi_xmlrpc_http_page_data_t* html_p_data = (mi_xmlrpc_http_page_data_t*)param; mi_xmlrpc_http_flush_content(&html_p_data->page, html_p_data->buffer.len, @@ -552,7 +576,7 @@ struct mi_root* mi_xmlrpc_http_run_mi_cmd(const str* arg, if (mi_cmd) free_mi_tree(mi_cmd); if(doc)xmlFree(doc);doc=NULL; - if(esc_val.s);shm_free(esc_val.s); + if(esc_val.s) shm_free(esc_val.s); return mi_rpl; xml_error: @@ -562,52 +586,92 @@ struct mi_root* mi_xmlrpc_http_run_mi_cmd(const str* arg, } -static inline int mi_xmlrpc_http_write_node(char** pointer, char* buf, int max_page_len, - struct mi_node *node, int level) +static int mi_xmlrpc_http_recur_write_node(char** pointer, char* buf, int max_page_len, + struct mi_node *node, int level, int dump_name, int flush) { struct mi_attr *attr; str temp_holder; int temp_counter; - int insert_node_separator; - /* name and value */ - if (node->name.s!=NULL) { - for(;level>0;level--) { - MI_XMLRPC_HTTP_COPY(*pointer, - MI_XMLRPC_HTTP_NODE_INDENT); - } - MI_XMLRPC_HTTP_COPY(*pointer, - node->name); - insert_node_separator = 1; - } else { - insert_node_separator = 0; + if(dump_name){ + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_START); + + if (node->name.s!=NULL) + MI_XMLRPC_HTTP_ESC_COPY(*pointer, node->name, temp_holder, temp_counter); + else + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_DEFAULT); + + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_END); } - if (node->value.s!=NULL) { - if (insert_node_separator) { - MI_XMLRPC_HTTP_COPY(*pointer, - MI_XMLRPC_HTTP_NODE_SEPARATOR); - insert_node_separator = 0; + + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_START); + + if(!node->kids && !node->attributes){ + if (node->value.s!=NULL) + MI_XMLRPC_HTTP_ESC_COPY(*pointer, node->value, temp_holder, temp_counter); + else + MI_XMLRPC_HTTP_ESC_COPY(*pointer, node->value, temp_holder, temp_counter); + } else { + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_STRUCT_START); + + if (node->value.s!=NULL){ + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_MEMBER_START); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_START); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_DEFAULT); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_START); + MI_XMLRPC_HTTP_ESC_COPY(*pointer, node->value, temp_holder, temp_counter); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_MEMBER_END); } - MI_XMLRPC_HTTP_ESC_COPY(*pointer, node->value, - temp_holder, temp_counter); - } - /* attributes */ - for(attr=node->attributes;attr!=NULL;attr=attr->next) { - if (insert_node_separator) { - MI_XMLRPC_HTTP_COPY(*pointer, - MI_XMLRPC_HTTP_NODE_SEPARATOR); - insert_node_separator = 0; + + if (node->attributes != NULL){ + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_MEMBER_START); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_START); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_ATTRIBUTES_DEFAULT); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_START); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_STRUCT_START); + + for(attr = node->attributes; attr != NULL; attr = attr->next) { + if (attr->name.s!=NULL) { + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_MEMBER_START); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_START); + MI_XMLRPC_HTTP_ESC_COPY(*pointer, attr->name,temp_holder,temp_counter); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_START); + + if (attr->value.s!=NULL) + MI_XMLRPC_HTTP_ESC_COPY(*pointer, attr->value,temp_holder,temp_counter); + else + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_DEFAULT); + + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_MEMBER_END); + } + } + + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_STRUCT_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_MEMBER_END); } - if (attr->name.s!=NULL) { - MI_XMLRPC_HTTP_COPY_3(*pointer, - MI_XMLRPC_HTTP_ATTR_SEPARATOR, - attr->name, - MI_XMLRPC_HTTP_ATTR_VAL_SEPARATOR); - MI_XMLRPC_HTTP_ESC_COPY(*pointer, attr->value, - temp_holder, temp_counter); + + if (node->kids != NULL) { + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_MEMBER_START); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_START); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_KIDS_DEFAULT); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_START); + mi_xmlrpc_http_recur_write_tree(pointer, buf, max_page_len, node->kids, level + 3, node->flags, flush, node, MI_XMLRPC_FULL_OBJECT); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_MEMBER_END); } + + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_STRUCT_END); } - MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_CR); + + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_END); + return 0; error: LM_ERR("buffer 2 small: *pointer=[%p] buf=[%p] max_page_len=[%d]\n", @@ -615,17 +679,18 @@ static inline int mi_xmlrpc_http_write_node(char** pointer, char* buf, int max_p return -1; } - +/* static int mi_xmlrpc_http_recur_flush_tree(char** pointer, char *buf, int max_page_len, struct mi_node *tree, int level) { struct mi_node *kid, *tmp; int ret; + LM_DBG("flushing tree"); for(kid = tree->kids ; kid ; ){ if (!(kid->flags & MI_WRITTEN)) { - if (mi_xmlrpc_http_write_node(pointer, buf, max_page_len, - kid, level)!=0) + if (mi_xmlrpc_http_recur_write_node(pointer, buf, max_page_len, + kid, level, 1)!=0) return -1; kid->flags |= MI_WRITTEN; } @@ -641,46 +706,121 @@ static int mi_xmlrpc_http_recur_flush_tree(char** pointer, char *buf, int max_pa tree->kids = kid; if(!tmp->kids){ - /* this node does not have any kids */ + free_mi_node(tmp); } } else { - /* the node will have more kids => - * to keep the tree shape, - * do not flush any other node for now */ + return 1; } } return 0; -} +} */ + +void flush_node (struct mi_node *parent, struct mi_node *prev) { + struct mi_node *freed; + + if(!prev){ + freed = parent->kids; + parent->kids = freed->next; + } else { + freed = prev->next; + prev->next = prev->next->next; + } + if(!freed->kids) + free_mi_node(freed); +} static int mi_xmlrpc_http_recur_write_tree(char** pointer, char *buf, int max_page_len, - struct mi_node *tree, int level) + struct mi_node *tree, int level, unsigned int flags, int flush, struct mi_node *parent, int object_flags) { - for( ; tree ; tree=tree->next ) { - if (!(tree->flags & MI_WRITTEN)) { - if (mi_xmlrpc_http_write_node(pointer, buf, max_page_len, - tree, level)!=0){ - return -1; + + struct mi_node *t, *prev, *next; + str temp_holder; + int temp_counter; + + if (flags & MI_IS_ARRAY) { + LM_DBG("Treated as an array\n"); + + if(object_flags & MI_XMLRPC_START_OBJECT){ + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_STRUCT_START); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_MEMBER_START); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_START); + + if (tree->name.s!=NULL) + MI_XMLRPC_HTTP_ESC_COPY(*pointer, tree->name, temp_holder, temp_counter); + else + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_DEFAULT); + + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_NAME_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_START); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_ARRAY_START); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_DATA_START); + } + + prev = NULL; + t = tree; + while(t) { + mi_xmlrpc_http_recur_write_node(pointer, buf, max_page_len,t, level + 4, 0, flush); + t->flags |= MI_WRITTEN; + if(flush && !(t->flags & MI_NOT_COMPLETED)){ + next = t->next; + flush_node(parent, prev); + t = next; + } else { + prev = t; + t = t->next; } } - if (tree->kids) { - if (mi_xmlrpc_http_recur_write_tree(pointer, buf, max_page_len, - tree->kids, level+1)<0){ - return -1; + + if (object_flags & MI_XMLRPC_END_OBJECT) { + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_DATA_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_ARRAY_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_VALUE_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_MEMBER_END); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_STRUCT_END); + } + } else { + LM_DBG("Treated as an hash\n"); + if (object_flags & MI_XMLRPC_START_OBJECT) { + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_STRUCT_START); + } + prev = NULL; + t = tree; + while(t) { + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_MEMBER_START); + mi_xmlrpc_http_recur_write_node(pointer, buf, max_page_len,t, level + 2, 1, flush); + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_MEMBER_END); + + t->flags |= MI_WRITTEN; + if(flush && !(t->flags & MI_NOT_COMPLETED)){ + next = t->next; + flush_node(parent, prev); + t = next; + } else{ + prev = t; + t = t->next; } } + if (object_flags & MI_XMLRPC_END_OBJECT) { + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_STRUCT_END); + } } + return 0; -} +error: + LM_ERR("buffer 2 small\n"); + return -1; +} +/* int mi_xmlrpc_http_build_header(str *page, int max_page_len, struct mi_root *tree, int flush) { char *p, *buf; - + LM_DBG("in build header inceput\n"); if (page->s == NULL) { LM_ERR("Please provide a valid page\n"); return -1; @@ -694,16 +834,19 @@ int mi_xmlrpc_http_build_header(str *page, int max_page_len, tree->node.flags |= MI_WRITTEN; } if (flush) { - if (mi_xmlrpc_http_recur_flush_tree(&p, buf, max_page_len, - &tree->node, 0)<0) + LM_DBG("UN INCEPUT flush_treexx build header\n"); + if (mi_xmlrpc_http_recur_write_tree(&p, buf, max_page_len, + tree->node.kids, 0, tree->node.flags, 1, &tree->node)<0) return -1; } else { + LM_DBG("UN INCEPUT scris_fara_free build header\n"); if (mi_xmlrpc_http_recur_write_tree(&p, buf, max_page_len, - tree->node.kids, 0)<0) + tree->node.kids, 0, tree->node.flags, 0, NULL)<0) return -1; } MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_STOP); } + LM_DBG("in build header sfarsit\n"); page->len = p - page->s; return 0; @@ -711,7 +854,7 @@ int mi_xmlrpc_http_build_header(str *page, int max_page_len, LM_ERR("buffer 2 small\n"); page->len = p - page->s; return -1; -} +}*/ int mi_xmlrpc_http_build_content(str *page, int max_page_len, @@ -720,20 +863,31 @@ int mi_xmlrpc_http_build_content(str *page, int max_page_len, char *p, *buf; if (page->len==0) { - if (0!=mi_xmlrpc_http_build_header(page, max_page_len, tree, 0)) - return -1; + p = buf = page->s; + MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_START); + if (mi_xmlrpc_http_recur_write_tree(&p, buf, max_page_len, + tree->node.kids, 0, tree->node.flags, 0, NULL,MI_XMLRPC_FULL_OBJECT)<0) + return -1; + MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_STOP); + page->len = p - page->s; } else { buf = page->s; p = page->s + page->len; - if (tree) { /* Build mi reply */ if (mi_xmlrpc_http_recur_write_tree(&p, buf, max_page_len, - tree->node.kids, 0)<0) + tree->node.kids, 0, tree->node.flags, 0, NULL, MI_XMLRPC_END_OBJECT) < 0) return -1; + MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_STOP); page->len = p - page->s; } } + + //LM_DBG("mesaj :\n %.*s\n", page->len, page->s); return 0; +error: + LM_ERR("buffer 2 small\n"); + page->len = p - page->s; + return -1; } @@ -742,6 +896,7 @@ int mi_xmlrpc_http_build_page(str *page, int max_page_len, { if (0!=mi_xmlrpc_http_build_content(page, max_page_len, tree)) return -1; + return 0; } @@ -750,18 +905,28 @@ int mi_xmlrpc_http_flush_content(str *page, int max_page_len, struct mi_root* tree) { char *p, *buf; - - if (page->len==0) - if (0!=mi_xmlrpc_http_build_header(page, max_page_len, tree, 1)) - return -1; - buf = page->s; - p = page->s + page->len; - - if (tree) { /* Build mi reply */ - if (mi_xmlrpc_http_recur_flush_tree(&p, buf, max_page_len, - &tree->node, 0)<0) + if (page->len==0){ + p = buf = page->s; + MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_START); + if (mi_xmlrpc_http_recur_write_tree(&p, buf, max_page_len, + tree->node.kids, 0, tree->node.flags, 1, &tree->node,MI_XMLRPC_START_OBJECT)<0) return -1; page->len = p - page->s; + return 0; + } else { + buf = page->s; + p = page->s + page->len; + + if (tree) { /* Build mi reply */ + if (mi_xmlrpc_http_recur_write_tree(&p, buf, max_page_len, + tree->node.kids, 0, tree->node.flags, 1, &tree->node, 0)<0) + return -1; + page->len = p - page->s; + } } return 0; +error: + LM_ERR("buffer 2 small\n"); + page->len = p - page->s; + return -1; } diff --git a/modules/mi_xmlrpc_ng/http_fnc.h b/modules/mi_xmlrpc_ng/http_fnc.h index 18e79170a8c..584a3ee738e 100644 --- a/modules/mi_xmlrpc_ng/http_fnc.h +++ b/modules/mi_xmlrpc_ng/http_fnc.h @@ -22,15 +22,18 @@ * 2013-03-04 first version (osas) */ - #ifndef _MI_XMLRPC_HTTP_HTTP_FNC_H #define _MI_XMLRPC_HTTP_HTTP_FNC_H #define MI_XMLRPC_XML_START "\r\n\r\n" \ - "\r\n" -#define MI_XMLRPC_XML_STOP "" \ - "\r\n\r\n\r\n" + "encoding=\"UTF-8\"?>\r\n\r\n" \ + "\r\n" +#define MI_XMLRPC_XML_STOP "\r\n\r\n" + + +#define MI_XMLRPC_START_OBJECT (1<<0) +#define MI_XMLRPC_END_OBJECT (1<<1) +#define MI_XMLRPC_FULL_OBJECT 3 typedef struct mi_xmlrpc_http_html_page_data_ { str page; From f2a1e3db40cf5b687970b2dec166dd28a0e884e6 Mon Sep 17 00:00:00 2001 From: Cerghit Ionel Date: Tue, 11 Aug 2015 14:57:00 +0300 Subject: [PATCH 2/2] Add module parameter to chose response formatting add mi_xmlrpc_ng_format_version parameter to let the user choose between the two ways of formatting output, a value of 1 means the old formating and a value of 2 means the new formatting which is the default. --- modules/mi_xmlrpc_ng/http_fnc.c | 329 +++++++++++++++++++------- modules/mi_xmlrpc_ng/http_fnc.h | 14 +- modules/mi_xmlrpc_ng/mi_xmlrpc_http.c | 2 + 3 files changed, 253 insertions(+), 92 deletions(-) diff --git a/modules/mi_xmlrpc_ng/http_fnc.c b/modules/mi_xmlrpc_ng/http_fnc.c index 040179c147c..699d7a0806d 100644 --- a/modules/mi_xmlrpc_ng/http_fnc.c +++ b/modules/mi_xmlrpc_ng/http_fnc.c @@ -48,6 +48,7 @@ extern str http_root; +extern int version; mi_xmlrpc_http_page_data_t html_page_data; @@ -230,7 +231,15 @@ static int mi_xmlrpc_http_recur_write_tree(char** pointer, char *buf, int max_pa struct mi_node *tree, int level, unsigned int flags, int flush, struct mi_node *parent, int object_flags); static int mi_xmlrpc_http_recur_write_node(char** pointer, char* buf, int max_page_len, struct mi_node *node, int level, int dump_name, int flush); +static int mi_xmlrpc_http_recur_write_tree_old(char** pointer, char *buf, int max_page_len, + struct mi_node *tree, int level); +static int mi_xmlrpc_http_recur_flush_tree(char** pointer, char *buf, int max_page_len, + struct mi_node *tree, int level); +static int mi_xmlrpc_http_build_content_old(str *page, int max_page_len, + struct mi_root* tree); +static int mi_xmlrpc_http_write_node_old(char** pointer, char* buf, int max_page_len, + struct mi_node *node, int level); static const str MI_XMLRPC_HTTP_CR = str_init("\n"); static const str MI_XMLRPC_HTTP_SLASH = str_init("/"); @@ -243,6 +252,8 @@ static const str MI_XMLRPC_HTTP_ATTR_VAL_SEPARATOR = str_init("="); static const str MI_XMLRPC_HTTP_XML_START = str_init(MI_XMLRPC_XML_START); static const str MI_XMLRPC_HTTP_XML_STOP = str_init(MI_XMLRPC_XML_STOP); +static const str MI_XMLRPC_HTTP_XML_START_VER2 = str_init(MI_XMLRPC_XML_START_VER2); +static const str MI_XMLRPC_HTTP_XML_STOP_VER2 = str_init(MI_XMLRPC_XML_STOP_VER2); static const str MI_XMLRPC_HTTP_ESC_LT = str_init("<"); /* < */ static const str MI_XMLRPC_HTTP_ESC_GT = str_init(">"); /* > */ @@ -336,7 +347,8 @@ void mi_xmlrpc_http_destroy_async_lock(void) int mi_xmlrpc_http_flush_content(str *page, int max_page_len, struct mi_root* tree); - +int mi_xmlrpc_http_flush_content_old(str *page, int max_page_len, + struct mi_root* tree); int mi_xmlrpc_http_flush_tree(void* param, struct mi_root *tree) @@ -347,9 +359,21 @@ int mi_xmlrpc_http_flush_tree(void* param, struct mi_root *tree) } mi_xmlrpc_http_page_data_t* html_p_data = (mi_xmlrpc_http_page_data_t*)param; - mi_xmlrpc_http_flush_content(&html_p_data->page, - html_p_data->buffer.len, - tree); + + switch(version) { + case MI_XMLRPC_FORMATED_OUTPUT: + mi_xmlrpc_http_flush_content(&html_p_data->page, + html_p_data->buffer.len, tree); + break; + case MI_XMLRPC_UNFORMATED_OUTPUT: + mi_xmlrpc_http_flush_content_old(&html_p_data->page, + html_p_data->buffer.len, tree); + break; + default: + LM_ERR("Version param not set acordingly"); + return -1; + + } return 0; } @@ -679,44 +703,6 @@ static int mi_xmlrpc_http_recur_write_node(char** pointer, char* buf, int max_pa return -1; } -/* -static int mi_xmlrpc_http_recur_flush_tree(char** pointer, char *buf, int max_page_len, - struct mi_node *tree, int level) -{ - struct mi_node *kid, *tmp; - int ret; - LM_DBG("flushing tree"); - - for(kid = tree->kids ; kid ; ){ - if (!(kid->flags & MI_WRITTEN)) { - if (mi_xmlrpc_http_recur_write_node(pointer, buf, max_page_len, - kid, level, 1)!=0) - return -1; - kid->flags |= MI_WRITTEN; - } - if ((ret = mi_xmlrpc_http_recur_flush_tree(pointer, buf, max_page_len, - tree->kids, level+1))<0){ - return -1; - } else if (ret > 0) { - return ret; - } - if (!(kid->flags & MI_NOT_COMPLETED)){ - tmp = kid; - kid = kid->next; - tree->kids = kid; - - if(!tmp->kids){ - - free_mi_node(tmp); - } - } else { - - return 1; - } - } - return 0; -} */ - void flush_node (struct mi_node *parent, struct mi_node *prev) { struct mi_node *freed; @@ -815,48 +801,6 @@ static int mi_xmlrpc_http_recur_write_tree(char** pointer, char *buf, int max_pa } -/* -int mi_xmlrpc_http_build_header(str *page, int max_page_len, - struct mi_root *tree, int flush) -{ - char *p, *buf; - LM_DBG("in build header inceput\n"); - if (page->s == NULL) { - LM_ERR("Please provide a valid page\n"); - return -1; - } - p = buf = page->s; - - if (tree) { - LM_DBG("return code: %d\n", tree->code); - if (!(tree->node.flags & MI_WRITTEN)) { - MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_START); - tree->node.flags |= MI_WRITTEN; - } - if (flush) { - LM_DBG("UN INCEPUT flush_treexx build header\n"); - if (mi_xmlrpc_http_recur_write_tree(&p, buf, max_page_len, - tree->node.kids, 0, tree->node.flags, 1, &tree->node)<0) - return -1; - } else { - LM_DBG("UN INCEPUT scris_fara_free build header\n"); - if (mi_xmlrpc_http_recur_write_tree(&p, buf, max_page_len, - tree->node.kids, 0, tree->node.flags, 0, NULL)<0) - return -1; - } - MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_STOP); - } - LM_DBG("in build header sfarsit\n"); - - page->len = p - page->s; - return 0; -error: - LM_ERR("buffer 2 small\n"); - page->len = p - page->s; - return -1; -}*/ - - int mi_xmlrpc_http_build_content(str *page, int max_page_len, struct mi_root* tree) { @@ -864,11 +808,11 @@ int mi_xmlrpc_http_build_content(str *page, int max_page_len, if (page->len==0) { p = buf = page->s; - MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_START); + MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_START_VER2); if (mi_xmlrpc_http_recur_write_tree(&p, buf, max_page_len, tree->node.kids, 0, tree->node.flags, 0, NULL,MI_XMLRPC_FULL_OBJECT)<0) return -1; - MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_STOP); + MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_STOP_VER2); page->len = p - page->s; } else { buf = page->s; @@ -877,7 +821,7 @@ int mi_xmlrpc_http_build_content(str *page, int max_page_len, if (mi_xmlrpc_http_recur_write_tree(&p, buf, max_page_len, tree->node.kids, 0, tree->node.flags, 0, NULL, MI_XMLRPC_END_OBJECT) < 0) return -1; - MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_STOP); + MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_STOP_VER2); page->len = p - page->s; } } @@ -894,9 +838,20 @@ int mi_xmlrpc_http_build_content(str *page, int max_page_len, int mi_xmlrpc_http_build_page(str *page, int max_page_len, struct mi_root *tree) { - if (0!=mi_xmlrpc_http_build_content(page, max_page_len, tree)) + switch(version) { + case MI_XMLRPC_FORMATED_OUTPUT: + if (0!=mi_xmlrpc_http_build_content(page, max_page_len, tree)) + return -1; + break; + case MI_XMLRPC_UNFORMATED_OUTPUT: + if (0!=mi_xmlrpc_http_build_content_old(page, max_page_len, tree)) + return -1; + break; + default: + LM_ERR("Version param not set acordingly"); return -1; - + + } return 0; } @@ -907,7 +862,7 @@ int mi_xmlrpc_http_flush_content(str *page, int max_page_len, char *p, *buf; if (page->len==0){ p = buf = page->s; - MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_START); + MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_START_VER2); if (mi_xmlrpc_http_recur_write_tree(&p, buf, max_page_len, tree->node.kids, 0, tree->node.flags, 1, &tree->node,MI_XMLRPC_START_OBJECT)<0) return -1; @@ -930,3 +885,197 @@ int mi_xmlrpc_http_flush_content(str *page, int max_page_len, page->len = p - page->s; return -1; } + + +/* old implementations for less formated ouput */ + +int mi_xmlrpc_http_build_header(str *page, int max_page_len, + struct mi_root *tree, int flush) +{ + char *p, *buf; + + if (page->s == NULL) { + LM_ERR("Please provide a valid page\n"); + return -1; + } + p = buf = page->s; + + if (tree) { + LM_DBG("return code: %d\n", tree->code); + if (!(tree->node.flags & MI_WRITTEN)) { + MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_START); + tree->node.flags |= MI_WRITTEN; + } + if (flush) { + if (mi_xmlrpc_http_recur_flush_tree(&p, buf, max_page_len, + &tree->node, 0)<0) + return -1; + } else { + if (mi_xmlrpc_http_recur_write_tree_old(&p, buf, max_page_len, + tree->node.kids, 0)<0) + return -1; + } + MI_XMLRPC_HTTP_COPY(p, MI_XMLRPC_HTTP_XML_STOP); + } + + page->len = p - page->s; + return 0; +error: + LM_ERR("buffer 2 small\n"); + page->len = p - page->s; + return -1; +} + +static int mi_xmlrpc_http_build_content_old(str *page, int max_page_len, + struct mi_root* tree) +{ + char *p, *buf; + + if (page->len==0) { + if (0!=mi_xmlrpc_http_build_header(page, max_page_len, tree, 0)) + return -1; + } else { + buf = page->s; + p = page->s + page->len; + + if (tree) { /* Build mi reply */ + if (mi_xmlrpc_http_recur_write_tree_old(&p, buf, max_page_len, + tree->node.kids, 0)<0) + return -1; + page->len = p - page->s; + } + } + return 0; +} + +int mi_xmlrpc_http_flush_content_old(str *page, int max_page_len, + struct mi_root* tree) +{ + char *p, *buf; + + if (page->len==0) + if (0!=mi_xmlrpc_http_build_header(page, max_page_len, tree, 1)) + return -1; + buf = page->s; + p = page->s + page->len; + + if (tree) { /* Build mi reply */ + if (mi_xmlrpc_http_recur_flush_tree(&p, buf, max_page_len, + &tree->node, 0)<0) + return -1; + page->len = p - page->s; + } + return 0; +} + +static int mi_xmlrpc_http_recur_flush_tree(char** pointer, char *buf, int max_page_len, + struct mi_node *tree, int level) +{ + struct mi_node *kid, *tmp; + int ret; + LM_DBG("flushing tree"); + + for(kid = tree->kids ; kid ; ){ + if (!(kid->flags & MI_WRITTEN)) { + if (mi_xmlrpc_http_write_node_old(pointer, buf, max_page_len, + kid, level)!=0) + return -1; + kid->flags |= MI_WRITTEN; + } + if ((ret = mi_xmlrpc_http_recur_flush_tree(pointer, buf, max_page_len, + tree->kids, level+1))<0){ + return -1; + } else if (ret > 0) { + return ret; + } + if (!(kid->flags & MI_NOT_COMPLETED)){ + tmp = kid; + kid = kid->next; + tree->kids = kid; + + if(!tmp->kids){ + + free_mi_node(tmp); + } + } else { + + return 1; + } + } + return 0; +} + +static int mi_xmlrpc_http_write_node_old(char** pointer, char* buf, int max_page_len, + struct mi_node *node, int level) +{ + struct mi_attr *attr; + str temp_holder; + int temp_counter; + int insert_node_separator; + + /* name and value */ + if (node->name.s!=NULL) { + for(;level>0;level--) { + MI_XMLRPC_HTTP_COPY(*pointer, + MI_XMLRPC_HTTP_NODE_INDENT); + } + MI_XMLRPC_HTTP_COPY(*pointer, + node->name); + insert_node_separator = 1; + } else { + insert_node_separator = 0; + } + if (node->value.s!=NULL) { + if (insert_node_separator) { + MI_XMLRPC_HTTP_COPY(*pointer, + MI_XMLRPC_HTTP_NODE_SEPARATOR); + insert_node_separator = 0; + } + MI_XMLRPC_HTTP_ESC_COPY(*pointer, node->value, + temp_holder, temp_counter); + } + /* attributes */ + for(attr=node->attributes;attr!=NULL;attr=attr->next) { + if (insert_node_separator) { + MI_XMLRPC_HTTP_COPY(*pointer, + MI_XMLRPC_HTTP_NODE_SEPARATOR); + insert_node_separator = 0; + } + if (attr->name.s!=NULL) { + MI_XMLRPC_HTTP_COPY_3(*pointer, + MI_XMLRPC_HTTP_ATTR_SEPARATOR, + attr->name, + MI_XMLRPC_HTTP_ATTR_VAL_SEPARATOR); + MI_XMLRPC_HTTP_ESC_COPY(*pointer, attr->value, + temp_holder, temp_counter); + } + } + MI_XMLRPC_HTTP_COPY(*pointer, MI_XMLRPC_HTTP_CR); + return 0; +error: + LM_ERR("buffer 2 small: *pointer=[%p] buf=[%p] max_page_len=[%d]\n", + *pointer, buf, max_page_len); + return -1; +} + +static int mi_xmlrpc_http_recur_write_tree_old(char** pointer, char *buf, int max_page_len, + struct mi_node *tree, int level) +{ + for( ; tree ; tree=tree->next ) { + if (!(tree->flags & MI_WRITTEN)) { + if (mi_xmlrpc_http_write_node_old(pointer, buf, max_page_len, + tree, level)!=0){ + return -1; + } + } + if (tree->kids) { + if (mi_xmlrpc_http_recur_write_tree_old(pointer, buf, max_page_len, + tree->kids, level+1)<0){ + return -1; + } + } + } + return 0; +} + + diff --git a/modules/mi_xmlrpc_ng/http_fnc.h b/modules/mi_xmlrpc_ng/http_fnc.h index 584a3ee738e..f54d0cd16b4 100644 --- a/modules/mi_xmlrpc_ng/http_fnc.h +++ b/modules/mi_xmlrpc_ng/http_fnc.h @@ -25,16 +25,26 @@ #ifndef _MI_XMLRPC_HTTP_HTTP_FNC_H #define _MI_XMLRPC_HTTP_HTTP_FNC_H -#define MI_XMLRPC_XML_START "\r\n\r\n" \ + "\r\n" +#define MI_XMLRPC_XML_STOP "" \ + "\r\n\r\n\r\n" + + +#define MI_XMLRPC_XML_START_VER2 "\r\n\r\n" \ "\r\n" -#define MI_XMLRPC_XML_STOP "\r\n\r\n" +#define MI_XMLRPC_XML_STOP_VER2 "\r\n\r\n" #define MI_XMLRPC_START_OBJECT (1<<0) #define MI_XMLRPC_END_OBJECT (1<<1) #define MI_XMLRPC_FULL_OBJECT 3 +#define MI_XMLRPC_FORMATED_OUTPUT 2 +#define MI_XMLRPC_UNFORMATED_OUTPUT 1 + typedef struct mi_xmlrpc_http_html_page_data_ { str page; str buffer; diff --git a/modules/mi_xmlrpc_ng/mi_xmlrpc_http.c b/modules/mi_xmlrpc_ng/mi_xmlrpc_http.c index 23bcce23f15..144aae290de 100644 --- a/modules/mi_xmlrpc_ng/mi_xmlrpc_http.c +++ b/modules/mi_xmlrpc_ng/mi_xmlrpc_http.c @@ -45,6 +45,7 @@ int mi_xmlrpc_http_answer_to_connection (void *cls, void *connection, static ssize_t mi_xmlrpc_http_flush_data(void *cls, uint64_t pos, char *buf, size_t max); str http_root = str_init("RPC2"); +int version = 2; httpd_api_t httpd_api; @@ -57,6 +58,7 @@ static const str MI_XMLRPC_U_METHOD = str_init(MI_XMLRPC_XML_START /* module parameters */ static param_export_t mi_params[] = { {"mi_xmlrpc_ng_root", STR_PARAM, &http_root.s}, + {"mi_xmlrpc_ng_format_version", INT_PARAM, &version}, {0,0,0} };