Skip to content

Commit

Permalink
Fix handling of ASYNC MI commands
Browse files Browse the repository at this point in the history
Part of fixing #552.
Reported by @mqandeel .

Closes #552

(cherry picked from commit c08b033)

Conflicts:
	modules/mi_xmlrpc_ng/http_fnc.h
	modules/mi_xmlrpc_ng/mi_xmlrpc_http.c
  • Loading branch information
bogdan-iancu committed Aug 18, 2015
1 parent b1ee3a5 commit c8c8410
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 30 deletions.
62 changes: 37 additions & 25 deletions modules/mi_xmlrpc_ng/http_fnc.c
Expand Up @@ -335,43 +335,53 @@ static void mi_xmlrpc_http_close_async(struct mi_root *mi_rpl, struct mi_handler
struct mi_root *shm_rpl = NULL;
gen_lock_t* lock;
mi_xmlrpc_http_async_resp_data_t *async_resp_data;
int x;

if (hdl==NULL) {
LM_CRIT("null mi handler\n");
return;
}

LM_DBG("mi_root [%p], hdl [%p], hdl->param [%p], "
"*hdl->param [%p] and done [%u]\n",
mi_rpl, hdl, hdl->param, *(struct mi_root **)hdl->param, done);
LM_DBG("mi_root [%p], hdl [%p], hdl->param [%p] and done [%u]\n",
mi_rpl, hdl, hdl->param, done);

if (!done) {
/* we do not pass provisional stuff (yet) */
if (mi_rpl) free_mi_tree( mi_rpl );
return;
}

async_resp_data =
(mi_xmlrpc_http_async_resp_data_t*)((char*)hdl+sizeof(struct mi_handler));
async_resp_data = (mi_xmlrpc_http_async_resp_data_t*)(hdl+1);
lock = async_resp_data->lock;
lock_get(lock);
if (mi_rpl!=NULL && (shm_rpl=clone_mi_tree( mi_rpl, 1))!=NULL) {
*(struct mi_root **)hdl->param = shm_rpl;
} else {

if (mi_rpl==NULL || (shm_rpl=clone_mi_tree( mi_rpl, 1))==NULL) {
LM_WARN("Unable to process async reply [%p]\n", mi_rpl);
/* mark it as invalid */
hdl->param = NULL;
shm_rpl = MI_XMLRPC_ASYNC_FAILED;
}
LM_DBG("shm_rpl [%p], hdl [%p], hdl->param [%p], *hdl->param [%p]\n",
shm_rpl, hdl, hdl->param,
(hdl->param)?*(struct mi_root **)hdl->param:NULL);
if (mi_rpl) free_mi_tree(mi_rpl);

lock_get(lock);
if (hdl->param==NULL) {
hdl->param = shm_rpl;
x = 0;
} else {
x = 1;
}
LM_DBG("shm_rpl [%p], hdl [%p], hdl->param [%p]\n",
shm_rpl, hdl, hdl->param);
lock_release(lock);

if (mi_rpl) free_mi_tree(mi_rpl);
if (x) {
if (shm_rpl!=MI_XMLRPC_ASYNC_FAILED)
free_shm_mi_tree(shm_rpl);
shm_free(hdl);
}

return;
}


static inline struct mi_handler* mi_xmlrpc_http_build_async_handler(void)
{
struct mi_handler *hdl;
Expand All @@ -386,17 +396,15 @@ static inline struct mi_handler* mi_xmlrpc_http_build_async_handler(void)
}

memset(hdl, 0, len);
async_resp_data =
(mi_xmlrpc_http_async_resp_data_t*)((char*)hdl+sizeof(struct mi_handler));
async_resp_data = (mi_xmlrpc_http_async_resp_data_t*)(hdl+1);

hdl->handler_f = mi_xmlrpc_http_close_async;
hdl->param = (void*)&async_resp_data->tree;
hdl->param = NULL;

async_resp_data->lock = mi_xmlrpc_http_lock;

LM_DBG("hdl [%p], hdl->param [%p], *hdl->param [%p] mi_xmlrpc_http_lock=[%p]\n",
hdl, hdl->param, (hdl->param)?*(struct mi_root **)hdl->param:NULL,
async_resp_data->lock);
LM_DBG("hdl [%p], hdl->param [%p], mi_xmlrpc_http_lock=[%p]\n",
hdl, hdl->param, async_resp_data->lock);

return hdl;
}
Expand All @@ -406,9 +414,9 @@ struct mi_root* mi_xmlrpc_http_run_mi_cmd(const str* arg,
{
struct mi_cmd *f;
struct mi_node *node;
struct mi_root *mi_cmd;
struct mi_root *mi_rpl;
struct mi_handler *hdl;
struct mi_root *mi_cmd = NULL;
struct mi_root *mi_rpl = NULL;
struct mi_handler *hdl = NULL;
str miCmd;
xmlDocPtr doc;
xmlNodePtr methodCall_node;
Expand Down Expand Up @@ -463,7 +471,6 @@ struct mi_root* mi_xmlrpc_http_run_mi_cmd(const str* arg,
} else {
hdl = NULL;
}
*async_hdl = hdl;

if (f->flags&MI_NO_INPUT_FLAG) {
mi_cmd = NULL;
Expand Down Expand Up @@ -545,17 +552,22 @@ struct mi_root* mi_xmlrpc_http_run_mi_cmd(const str* arg,
LM_ERR("failed to process the command\n");
if (mi_cmd) free_mi_tree(mi_cmd);
goto xml_error;
} else if (mi_rpl != MI_ROOT_ASYNC_RPL) {
} else {
*page = html_page_data.page;
}
LM_DBG("got mi_rpl=[%p]\n",mi_rpl);

*async_hdl = hdl;

if (mi_cmd) free_mi_tree(mi_cmd);
if(doc)xmlFree(doc);doc=NULL;
if(esc_val.s);shm_free(esc_val.s);
return mi_rpl;

xml_error:
if (mi_cmd) free_mi_tree(mi_cmd);
if (hdl) shm_free(hdl);
*async_hdl = NULL;
if(doc)xmlFree(doc);doc=NULL;
if(esc_val.s);shm_free(esc_val.s);
return NULL;
Expand Down
4 changes: 3 additions & 1 deletion modules/mi_xmlrpc_ng/http_fnc.h
Expand Up @@ -32,14 +32,16 @@
#define MI_XMLRPC_XML_STOP "</string></value></param>" \
"\r\n</params>\r\n</methodResponse>\r\n"

#define MI_XMLRPC_ASYNC_FAILED ((void*)-2)
#define MI_XMLRPC_ASYNC_EXPIRED ((void*)-3)

typedef struct mi_xmlrpc_http_html_page_data_ {
str page;
str buffer;
}mi_xmlrpc_http_page_data_t;

typedef struct mi_xmlrpc_http_async_resp_data_ {
gen_lock_t* lock;
struct mi_root* tree;
}mi_xmlrpc_http_async_resp_data_t;


Expand Down
57 changes: 53 additions & 4 deletions modules/mi_xmlrpc_ng/mi_xmlrpc_http.c
Expand Up @@ -187,6 +187,50 @@ static ssize_t mi_xmlrpc_http_flush_data(void *cls, uint64_t pos, char *buf, siz
return -1;
}


#define MI_XMLRPC_MAX_WAIT 2*60*4
static inline struct mi_root*
mi_xmlrpc_wait_async_reply(struct mi_handler *hdl)
{
mi_xmlrpc_http_async_resp_data_t *async_resp_data =
(mi_xmlrpc_http_async_resp_data_t*)(hdl+1);
struct mi_root *mi_rpl;
int i;
int x;

for( i=0 ; i<MI_XMLRPC_MAX_WAIT ; i++ ) {
if (hdl->param)
break;
sleep_us(1000*500);
}

if (i==MI_XMLRPC_MAX_WAIT) {
/* no more waiting ....*/
lock_get(async_resp_data->lock);
if (hdl->param==NULL) {
hdl->param = MI_XMLRPC_ASYNC_EXPIRED;
x = 0;
} else {
x = 1;
}
lock_release(async_resp_data->lock);
if (x==0) {
LM_INFO("exiting before receiving reply\n");
return NULL;
}
}

mi_rpl = (struct mi_root *)hdl->param;
if (mi_rpl==MI_XMLRPC_ASYNC_FAILED)
mi_rpl = NULL;

/* free the async handler*/
shm_free(hdl);

return mi_rpl;
}


#define MI_XMLRPC_OK 200
#define MI_XMLRPC_NOT_ACCEPTABLE 406
#define MI_XMLRPC_INTERNAL_ERROR 500
Expand All @@ -201,6 +245,7 @@ int mi_xmlrpc_http_answer_to_connection (void *cls, void *connection,
struct mi_root *tree = NULL;
struct mi_handler *async_hdl;
int ret_code = MI_XMLRPC_OK;
int is_shm = 0;

LM_DBG("START *** cls=%p, connection=%p, url=%s, method=%s, "
"versio=%s, upload_data[%d]=%p, *con_cls=%p\n",
Expand All @@ -211,13 +256,17 @@ int mi_xmlrpc_http_answer_to_connection (void *cls, void *connection,
if (arg.s) {
tree = mi_xmlrpc_http_run_mi_cmd(&arg,
page, buffer, &async_hdl);
if (tree == MI_ROOT_ASYNC_RPL) {
LM_DBG("got an async reply\n");
tree = mi_xmlrpc_wait_async_reply(async_hdl);
async_hdl = NULL;
is_shm = 1;
}

if (tree == NULL) {
LM_ERR("no reply\n");
*page = MI_XMLRPC_U_ERROR;
ret_code = MI_XMLRPC_INTERNAL_ERROR;
} else if (tree == MI_ROOT_ASYNC_RPL) {
LM_DBG("got an async reply\n");
tree = NULL;
} else {
LM_DBG("building on page [%p:%d]\n",
page->s, page->len);
Expand All @@ -236,7 +285,7 @@ int mi_xmlrpc_http_answer_to_connection (void *cls, void *connection,
ret_code = MI_XMLRPC_INTERNAL_ERROR;
}
if (tree) {
free_mi_tree(tree);
is_shm?free_shm_mi_tree(tree):free_mi_tree(tree);
tree = NULL;
}
} else {
Expand Down

0 comments on commit c8c8410

Please sign in to comment.