Skip to content

Commit

Permalink
Merge branch 'AgalyaR-master'
Browse files Browse the repository at this point in the history
Resolves #968 Pull Request
  • Loading branch information
liviuchircu committed Oct 19, 2016
2 parents edad726 + 762cd79 commit c480700
Show file tree
Hide file tree
Showing 3 changed files with 264 additions and 3 deletions.
137 changes: 134 additions & 3 deletions modules/rest_client/rest_client.c
Expand Up @@ -62,6 +62,7 @@ static void mod_destroy(void);
*/
static int fixup_rest_get(void **param, int param_no);
static int fixup_rest_post(void **param, int param_no);
static int fixup_rest_put(void **param, int param_no);

/*
* Function headers
Expand All @@ -70,23 +71,31 @@ static int w_rest_get(struct sip_msg *msg, char *gp_url, char *body_pv,
char *ctype_pv, char *code_pv);
static int w_rest_post(struct sip_msg *msg, char *gp_url, char *gp_body,
char *gp_ctype, char *body_pv, char *ctype_pv, char *code_pv);
static int w_rest_put(struct sip_msg *msg, char *gp_url, char *gp_body,
char *gp_ctype, char *body_pv, char *ctype_pv, char *code_pv);

static int w_async_rest_get(struct sip_msg *msg, async_resume_module **resume_f,
void **resume_param, char *gp_url,
char *body_pv, char *ctype_pv, char *code_pv);
static int w_async_rest_post(struct sip_msg *msg, async_resume_module **resume_f,
void **resume_param, char *gp_url, char *gp_body,
char *gp_ctype, char *body_pv, char *ctype_pv, char *code_pv);
static int w_async_rest_put(struct sip_msg *msg, async_resume_module **resume_f,
void **resume_param, char *gp_url, char *gp_body,
char *gp_ctype, char *body_pv, char *ctype_pv, char *code_pv);

static int w_rest_append_hf(struct sip_msg *msg, char *gp_hfv);

static acmd_export_t acmds[] = {
{ "rest_get", (acmd_function)w_async_rest_get, 2, fixup_rest_get },
{ "rest_get", (acmd_function)w_async_rest_get, 3, fixup_rest_get },
{ "rest_get", (acmd_function)w_async_rest_get, 4, fixup_rest_get },
{ "rest_post", (acmd_function)w_async_rest_post, 4, fixup_rest_post },
{ "rest_post", (acmd_function)w_async_rest_post, 5, fixup_rest_post },
{ "rest_post", (acmd_function)w_async_rest_post, 6, fixup_rest_post },
{ "rest_post", (acmd_function)w_async_rest_post, 4, fixup_rest_post },
{ "rest_post", (acmd_function)w_async_rest_post, 5, fixup_rest_post },
{ "rest_post", (acmd_function)w_async_rest_post, 6, fixup_rest_post },
{ "rest_put", (acmd_function)w_async_rest_put, 4, fixup_rest_put },
{ "rest_put", (acmd_function)w_async_rest_put, 5, fixup_rest_put },
{ "rest_put", (acmd_function)w_async_rest_put, 6, fixup_rest_put },
{ 0, 0, 0, 0 }
};

Expand All @@ -112,6 +121,15 @@ static cmd_export_t cmds[] = {
{ "rest_post",(cmd_function)w_rest_post, 6, fixup_rest_post, 0,
REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|
ONREPLY_ROUTE|STARTUP_ROUTE|TIMER_ROUTE },
{ "rest_put",(cmd_function)w_rest_put, 4, fixup_rest_put, 0,
REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|
ONREPLY_ROUTE|STARTUP_ROUTE|TIMER_ROUTE },
{ "rest_put",(cmd_function)w_rest_put, 5, fixup_rest_put, 0,
REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|
ONREPLY_ROUTE|STARTUP_ROUTE|TIMER_ROUTE },
{ "rest_put",(cmd_function)w_rest_put, 6, fixup_rest_put, 0,
REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|
ONREPLY_ROUTE|STARTUP_ROUTE|TIMER_ROUTE },
{ "rest_append_hf",(cmd_function)w_rest_append_hf, 1, fixup_spve_null, 0,
REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|
ONREPLY_ROUTE|STARTUP_ROUTE|TIMER_ROUTE },
Expand Down Expand Up @@ -280,6 +298,24 @@ static int fixup_rest_post(void **param, int param_no)
}
}

static int fixup_rest_put(void **param, int param_no)
{
switch (param_no) {
case 1:
case 2:
case 3:
return fixup_spve(param);
case 4:
case 5:
case 6:
return fixup_pvar(param);

default:
LM_ERR("Too many parameters!\n");
return -1;
}
}

/**************************** Module functions *******************************/

static int w_rest_get(struct sip_msg *msg, char *gp_url, char *body_pv,
Expand Down Expand Up @@ -320,6 +356,31 @@ static int w_rest_post(struct sip_msg *msg, char *gp_url, char *gp_body,
(pv_spec_p)ctype_pv, (pv_spec_p)code_pv);
}

static int w_rest_put(struct sip_msg *msg, char *gp_url, char *gp_body,
char *gp_ctype, char *body_pv, char *ctype_pv, char *code_pv)
{
str url, body, ctype = { NULL, 0 };

if (fixup_get_svalue(msg, (gparam_p)gp_url, &url) != 0) {
LM_ERR("Invalid HTTP URL pseudo variable!\n");
return -1;
}

if (fixup_get_svalue(msg, (gparam_p)gp_body, &body) != 0) {
LM_ERR("Invalid HTTP PUT body pseudo variable!\n");
return -1;
}

if (gp_ctype && fixup_get_svalue(msg, (gparam_p)gp_ctype, &ctype) != 0) {
LM_ERR("Invalid HTTP PUT content type pseudo variable!\n");
return -1;
}

return rest_put_method(msg, url.s, body.s, ctype.s, (pv_spec_p)body_pv,
(pv_spec_p)ctype_pv, (pv_spec_p)code_pv);
}


static void set_output_pv_params(struct sip_msg *msg, str *body_in, pv_spec_p body_pv, str *ctype_in,
pv_spec_p ctype_pv, CURL *handle, pv_spec_p code_pv)
{
Expand Down Expand Up @@ -483,6 +544,76 @@ static int w_async_rest_post(struct sip_msg *msg, async_resume_module **resume_f
return 1;
}

static int w_async_rest_put(struct sip_msg *msg, async_resume_module **resume_f,
void **resume_param, char *gp_url, char *gp_body,
char *gp_ctype, char *body_pv, char *ctype_pv, char *code_pv)
{
rest_async_param *param;
str url, body, ctype = { NULL, 0 };
int read_fd;

if (fixup_get_svalue(msg, (gparam_p)gp_url, &url) != 0) {
LM_ERR("Invalid HTTP URL pseudo variable!\n");
return -1;
}

if (fixup_get_svalue(msg, (gparam_p)gp_body, &body) != 0) {
LM_ERR("Invalid HTTP PUT body pseudo variable!\n");
return -1;
}

if (gp_ctype && fixup_get_svalue(msg, (gparam_p)gp_ctype, &ctype) != 0) {
LM_ERR("Invalid HTTP PUT content type pseudo variable!\n");
return -1;
}

LM_DBG("async rest put '%.*s' %p %p %p\n", url.len, url.s, body_pv, ctype_pv, code_pv);

param = pkg_malloc(sizeof *param);
if (!param) {
LM_ERR("no more shm\n");
return -1;
}
memset(param, '\0', sizeof *param);

read_fd = start_async_http_req(msg, REST_CLIENT_PUT, url.s, body.s, ctype.s,
&param->handle, &param->body, ctype_pv ? &param->ctype : NULL);

/* error occurred; no transfer done */
if (read_fd == ASYNC_NO_IO) {
*resume_param = NULL;
*resume_f = NULL;
/* keep default async status of NO_IO */
return -1;

/* no need for async - transfer already completed! */
} else if (read_fd == ASYNC_SYNC) {
set_output_pv_params(msg, &param->body, (pv_spec_p)body_pv,
&param->ctype, (pv_spec_p)ctype_pv,
param->handle, (pv_spec_p)code_pv);

pkg_free(param->body.s);
if (ctype_pv && param->ctype.s)
pkg_free(param->ctype.s);
curl_easy_cleanup(param->handle);
pkg_free(param);

return ASYNC_SYNC;
}

*resume_f = resume_async_http_req;

param->method = REST_CLIENT_PUT;
param->body_pv = (pv_spec_p)body_pv;
param->ctype_pv = (pv_spec_p)ctype_pv;
param->code_pv = (pv_spec_p)code_pv;
*resume_param = param;
/* async started with success */
async_status = read_fd;

return 1;
}

static int w_rest_append_hf(struct sip_msg *msg, char *gp_hfv)
{
str hfv;
Expand Down
127 changes: 127 additions & 0 deletions modules/rest_client/rest_methods.c
Expand Up @@ -154,6 +154,17 @@ int start_async_http_req(struct sip_msg *msg, enum rest_client_method method,
w_curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header_list);
}
break;
case REST_CLIENT_PUT:
w_curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "PUT");
w_curl_easy_setopt(handle, CURLOPT_POSTFIELDS, req_body);

if (req_ctype) {
sprintf(print_buff, "Content-Type: %s", req_ctype);
header_list = curl_slist_append(header_list, print_buff);
w_curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header_list);
}
break;

case REST_CLIENT_GET:
break;

Expand Down Expand Up @@ -616,6 +627,122 @@ int rest_post_method(struct sip_msg *msg, char *url, char *body, char *ctype,
return -1;
}

/**
* rest_put_method - performs an HTTP PUT request, stores results in pvars
* @msg: sip message struct
* @url: HTTP URL to be queried
* @ctype: Value for the "Content-Type: " header of the request
* @body: Body of the request
* @body_pv: pseudo var which will hold the result body
* @ctype_pv: pvar which will hold the result content type
* @code_pv: pvar to hold the HTTP return code
*/
int rest_put_method(struct sip_msg *msg, char *url, char *body, char *ctype,
pv_spec_p body_pv, pv_spec_p ctype_pv, pv_spec_p code_pv)
{
CURLcode rc;
CURL *handle = NULL;
long http_rc;
str st = { 0, 0 };
str res_body = { NULL, 0 }, tbody;
pv_value_t pv_val;

handle = curl_easy_init();
if (!handle) {
LM_ERR("Init curl handle failed!\n");
clean_header_list;
return -1;
}

if (ctype) {
sprintf(print_buff, "Content-Type: %s", ctype);
header_list = curl_slist_append(header_list, print_buff);
}

if (header_list)
w_curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header_list);

w_curl_easy_setopt(handle, CURLOPT_URL, url);
w_curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "PUT");
w_curl_easy_setopt(handle, CURLOPT_POSTFIELDS, body);

w_curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, connection_timeout);
w_curl_easy_setopt(handle, CURLOPT_TIMEOUT, curl_timeout);

w_curl_easy_setopt(handle, CURLOPT_VERBOSE, 1);
w_curl_easy_setopt(handle, CURLOPT_STDERR, stdout);
w_curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1);

w_curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_func);
w_curl_easy_setopt(handle, CURLOPT_WRITEDATA, &res_body);

w_curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, header_func);
w_curl_easy_setopt(handle, CURLOPT_HEADERDATA, &st);

if (ssl_capath)
w_curl_easy_setopt(handle, CURLOPT_CAPATH, ssl_capath);

if (!ssl_verifypeer)
w_curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L);

if (!ssl_verifyhost)
w_curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0L);

rc = curl_easy_perform(handle);
clean_header_list;
if (code_pv) {
curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_rc);
LM_DBG("Last response code: %ld\n", http_rc);

pv_val.flags = PV_VAL_INT|PV_TYPE_INT;
pv_val.ri = (int)http_rc;

if (pv_set_value(msg, code_pv, 0, &pv_val) != 0) {
LM_ERR("Set code pv value failed!\n");
goto cleanup;
}
}

if (rc != CURLE_OK) {
LM_ERR("curl_easy_perform: %s\n", curl_easy_strerror(rc));
goto cleanup;
}

tbody = res_body;
trim(&tbody);

pv_val.flags = PV_VAL_STR;
pv_val.rs = tbody;

if (pv_set_value(msg, body_pv, 0, &pv_val) != 0) {
LM_ERR("Set body pv value failed!\n");
goto cleanup;
}

if (res_body.s) {
pkg_free(res_body.s);
}

if (ctype_pv) {
pv_val.rs = st;

if (pv_set_value(msg, ctype_pv, 0, &pv_val) != 0) {
LM_ERR("Set content type pv value failed!\n");
goto cleanup;
}

if (st.s)
pkg_free(st.s);
}

curl_easy_cleanup(handle);
return 1;

cleanup:
curl_easy_cleanup(handle);
return -1;
}

/**
* rest_append_hf - add a custom HTTP header before a rest call
* @msg: sip message struct
Expand Down
3 changes: 3 additions & 0 deletions modules/rest_client/rest_methods.h
Expand Up @@ -44,6 +44,7 @@ extern int ssl_verifyhost;
/* Currently supported HTTP verbs */
enum rest_client_method {
REST_CLIENT_GET,
REST_CLIENT_PUT,
REST_CLIENT_POST
};

Expand All @@ -62,6 +63,8 @@ int rest_get_method(struct sip_msg *msg, char *url,
pv_spec_p body_pv, pv_spec_p ctype_pv, pv_spec_p code_pv);
int rest_post_method(struct sip_msg *msg, char *url, char *body, char *ctype,
pv_spec_p body_pv, pv_spec_p ctype_pv, pv_spec_p code_pv);
int rest_put_method(struct sip_msg *msg, char *url, char *body, char *ctype,
pv_spec_p body_pv, pv_spec_p ctype_pv, pv_spec_p code_pv);

int start_async_http_req(struct sip_msg *msg, enum rest_client_method method,
char *url, char *req_body, char *req_ctype,
Expand Down

0 comments on commit c480700

Please sign in to comment.