Hi Bogdan/Liviu,
I have downloaded 2.1.4 version if opensips and trying to use rest_put call in
async mode.
I have added the necessary code for rest_put () similar to rest_post() in
rest_methods.c, rest_methods.h and rest_client.c
If I just call, rest_put from config file, without async it works fine. I could
see rest_put() is called and do the necessary steps.
And am trying to call async from config file as,
async(rest_put("http://***url*** <http://***url***%20> ", "$fU,$tU,$ci ",
"application/json", "$var(body)", "$var(ct)", "$var(rcode)"),resume_put);
Further debugging I got some info that I can share with you so that you can
help me out easily.
Instead of calling rest_put asynchronously I have tried to call rest_post async
. I could able to see that HTTP request went out(from wireshark traces) and I
got 4xx response for the same.
With my code changes in place and when I call rest_put, am not seeing HTTP
request sent out.
Assuming rest_put only is not working, there should be some libcurl stuffs not
handled properly in 'start_async_http_req' for 'REST_CLIENT_PUT' case.
Am attaching the files. It contains code for rest_put only. I have removed
other code to reduce the file size. Can you please take a look guide me here.
Please let me know if you need more information on this.
Regards,
Agalya
From: [email protected]
[mailto:[email protected]] On Behalf Of Liviu Chircu
Sent: Friday, August 05, 2016 4:47 AM
To: [email protected]
Subject: Re: [OpenSIPS-Users] Asynchronous operation for REST queries
Hi Agalya,
1.11 has no async support at core level. If you need that, you will have to use
2.1+
Async rest_put() is currently not implemented, but its logic would be fairly
similar to the GET and POST counterparts.
Liviu Chircu
OpenSIPS Developer
http://www.opensips-solutions.com
On 04.08.2016 23:14, Ramachandran, Agalya (Contractor) wrote:
Hi team,
We are using opensips1.11.3 version for our project.
I have a question here. Right now we are using a REST API call from config file
for our project requirement and it is in synchronous mode currently.
>From the opensips document, I see asynchronous support at script level can be
>done in 2.1 version.
Is it possible to change in asynchronous mode in 1.11 version?
If not, is there a way to achieve asynchronous REST calls for the version of
opensips what we are using?
Also I see from documentation,
The following functions may also be called asynchronously:
*
avp_db_query<http://www.opensips.org/html/docs/modules/2.1.x/avpops.html#id294986>
*
rest_get<http://www.opensips.org/html/docs/modules/2.1.x/rest_client.html#id293741>
*
rest_post<http://www.opensips.org/html/docs/modules/2.1.x/rest_client.html#id293886>
* exec<http://www.opensips.org/html/docs/modules/2.1.x/exec#id294052>
Can rest_put can also be called asynchronously if we use 2.1 version ?
Please clarify.
Regards,
Agalya
_______________________________________________
Users mailing list
[email protected]<mailto:[email protected]>
http://lists.opensips.org/cgi-bin/mailman/listinfo/users
/*
* Copyright (C) 2013-2015 OpenSIPS Solutions
*
* This file is part of opensips, a free SIP server.
*
* opensips 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 2 of the License, or
* (at your option) any later version
*
* opensips 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* History:
* -------
* 2013-02-28: Created (Liviu)
*/
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
#include "../../async.h"
#include "../../sr_module.h"
#include "../../dprint.h"
#include "../../mem/mem.h"
#include "../../mem/shm_mem.h"
#include "../../mod_fix.h"
#include "rest_methods.h"
/*
* Module parameters
*/
long connection_timeout = 20;
long connection_timeout_ms;
long curl_timeout = 20;
char *ssl_capath;
/* libcurl enables these by default */
int ssl_verifypeer = 1;
int ssl_verifyhost = 1;
/*
* Module initialization and cleanup
*/
static int mod_init(void);
static int child_init(int rank);
static void mod_destroy(void);
/*
* Fixup functions
*/
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
*/
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 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_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 }
};
/*
* Exported functions
*/
static cmd_export_t cmds[] = {
{ "rest_get",(cmd_function)w_rest_get, 2, fixup_rest_get, 0,
REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|
ONREPLY_ROUTE|STARTUP_ROUTE|TIMER_ROUTE },
{ "rest_get",(cmd_function)w_rest_get, 3, fixup_rest_get, 0,
REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|
ONREPLY_ROUTE|STARTUP_ROUTE|TIMER_ROUTE },
{ "rest_get",(cmd_function)w_rest_get, 4, fixup_rest_get, 0,
REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|
ONREPLY_ROUTE|STARTUP_ROUTE|TIMER_ROUTE },
{ "rest_post",(cmd_function)w_rest_post, 4, fixup_rest_post, 0,
REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|
ONREPLY_ROUTE|STARTUP_ROUTE|TIMER_ROUTE },
{ "rest_post",(cmd_function)w_rest_post, 5, fixup_rest_post, 0,
REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|
ONREPLY_ROUTE|STARTUP_ROUTE|TIMER_ROUTE },
{ "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 },
{ 0, 0, 0, 0, 0, 0 }
};
/*
* Exported parameters
*/
static param_export_t params[] = {
{ "connection_timeout", INT_PARAM, &connection_timeout },
{ "curl_timeout", INT_PARAM, &curl_timeout
},
{ "ssl_capath", STR_PARAM, &ssl_capath
},
{ "ssl_verifypeer", INT_PARAM, &ssl_verifypeer
},
{ "ssl_verifyhost", INT_PARAM, &ssl_verifyhost
},
{ 0, 0, 0 }
};
/*
* Module parameter variables
*/
struct module_exports exports = {
"rest_client",
MOD_TYPE_DEFAULT,/* class of this module */
MODULE_VERSION, /* module version */
DEFAULT_DLFLAGS, /* dlopen flags */
NULL, /* OpenSIPS module dependencies */
cmds, /* Exported functions */
acmds, /* Exported async functions */
params, /* Exported parameters */
NULL, /* exported statistics */
NULL, /* exported MI functions */
NULL, /* exported pseudo-variables */
NULL, /* extra processes */
mod_init, /* module initialization function */
NULL, /* response function*/
mod_destroy,
child_init,/* per-child init function */
};
static void *osips_malloc(size_t size)
{
void *p = pkg_malloc(size);
return p;
}
static void *osips_calloc(size_t nmemb, size_t size)
{
void *p = pkg_malloc(nmemb * size);
if (p)
memset(p, '\0', nmemb * size);
return p;
}
static void *osips_realloc(void *ptr, size_t size)
{
void *p = pkg_realloc(ptr, size);
return p;
}
static char *osips_strdup(const char *cp)
{
char *rval;
int len;
len = strlen(cp) + 1;
rval = pkg_malloc(len);
if (!rval)
return NULL;
memcpy(rval, cp, len);
return rval;
}
static void osips_free(void *ptr)
{
if (ptr)
pkg_free(ptr);
}
static int mod_init(void)
{
LM_DBG("Initializing...\n");
connection_timeout_ms = connection_timeout * 1000L;
curl_global_init_mem(CURL_GLOBAL_ALL,
osips_malloc,
osips_free,
osips_realloc,
osips_strdup,
osips_calloc);
multi_handle = curl_multi_init();
LM_INFO("Module initialized!\n");
return 0;
}
static int child_init(int rank)
{
if (rank <= PROC_MAIN)
return 0;
multi_handle = curl_multi_init();
if (!multi_handle) {
LM_ERR("failed to init CURLM handle\n");
return -1;
}
return 0;
}
static void mod_destroy(void)
{
curl_global_cleanup();
}
/**************************** Fixup functions *******************************/
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_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 POST body pseudo variable!\n");
return -1;
}
if (gp_ctype && fixup_get_svalue(msg, (gparam_p)gp_ctype, &ctype) != 0)
{
LM_ERR("Invalid HTTP POST 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)
{
pv_value_t val;
long http_rc;
CURLcode rc;
val.flags = PV_VAL_STR;
val.rs = *body_in;
if (pv_set_value(msg, (pv_spec_p)body_pv, 0, &val) != 0)
LM_ERR("failed to set output body pv\n");
if (ctype_pv) {
val.rs = *ctype_in;
if (pv_set_value(msg, (pv_spec_p)ctype_pv, 0, &val) != 0)
LM_ERR("failed to set output ctype pv\n");
}
if (code_pv) {
rc = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE,
&http_rc);
if (rc != CURLE_OK)
LM_ERR("curl_easy_getinfo: %s\n",
curl_easy_strerror(rc));
LM_DBG("Last response code: %ld\n", http_rc);
val.flags = PV_VAL_INT|PV_TYPE_INT;
val.ri = (int)http_rc;
if (pv_set_value(msg, (pv_spec_p)code_pv, 0, &val) != 0)
LM_ERR("failed to set output code pv\n");
}
}
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 POST body pseudo variable!\n");
return -1;
}
if (gp_ctype && fixup_get_svalue(msg, (gparam_p)gp_ctype, &ctype) != 0)
{
LM_ERR("Invalid HTTP POST 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,
¶m->handle, ¶m->body, ctype_pv ?
¶m->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, ¶m->body, (pv_spec_p)body_pv,
¶m->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;
}
/*
* Copyright (C) 2013 OpenSIPS Solutions
*
* This file is part of opensips, a free SIP server.
*
* opensips 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 2 of the License, or
* (at your option) any later version
*
* opensips 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* History:
* -------
* 2013-02-28: Created (Liviu)
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
#include "../../mem/shm_mem.h"
#include "../../async.h"
#include "rest_methods.h"
#include "rest_cb.h"
static char print_buff[MAX_CONTENT_TYPE_LEN];
CURLM *multi_handle;
/* simultaneous ongoing transfers within this process */
static int transfers;
static int read_fds[FD_SETSIZE];
/* libcurl's reported running handles */
static int running_handles;
static long sleep_on_bad_timeout = 500; /* ms */
#define clean_header_list(list) \
do { \
if (list) { \
curl_slist_free_all(list); \
list = NULL; \
} \
} while (0)
#define w_curl_easy_setopt(h, opt, value) \
do { \
rc = curl_easy_setopt(h, opt, value); \
if (rc != CURLE_OK) { \
LM_ERR("curl_easy_setopt(%d): (%s)\n", opt,
curl_easy_strerror(rc)); \
goto cleanup; \
} \
} while (0)
static inline char is_new_transfer(int fd)
{
int it;
for (it = 0; it < transfers; it++) {
if (fd == read_fds[it])
return 0;
}
return 1;
}
static inline void add_transfer(int fd)
{
read_fds[transfers++] = fd;
}
static inline char del_transfer(int fd)
{
int it;
LM_DBG("del fd %d\n", fd);
for (it = 0; it < transfers; it++) {
if (fd == read_fds[it]) {
transfers--;
for (; it < transfers; it++)
read_fds[it] = read_fds[it + 1];
return 0;
}
}
return -1;
}
int generateRandomNumber()
{
srand ( time(NULL) );
int random_number = rand();
int rand_capped = random_number % 1000;
//LM_INFO("Random Number Generated: %d\n", rand_capped);
return rand_capped;
}
/**
* start_async_http_req - performs an HTTP request, stores results in pvars
* - TCP connect phase is synchronous, due to libcurl limitations
* - TCP read phase is asynchronous, thanks to the libcurl multi
interface
*
* @msg: sip message struct
* @method: HTTP verb
* @url: HTTP URL to be queried
* @req_body: Body of the request (NULL if not needed)
* @req_ctype: Value for the "Content-Type: " header of the request (same as ^)
* @out_handle: CURL easy handle used to perform the transfer
* @body: reply body; gradually reallocated as data arrives
* @ctype: will eventually hold the last "Content-Type" header of the
reply
*/
int start_async_http_req(struct sip_msg *msg, enum rest_client_method method,
char *url, char *req_body, char
*req_ctype,
CURL **out_handle, str *body, str
*ctype)
{
CURL *handle;
CURLcode rc;
CURLMcode mrc;
struct curl_slist *list = NULL;
fd_set rset, wset, eset;
int max_fd, fd, i;
long busy_wait, timeout;
long retry_time, check_time = 5; /* 5ms looping time */
int msgs_in_queue;
CURLMsg *cmsg;
if (transfers == FD_SETSIZE) {
LM_ERR("too many ongoing tranfers: %d\n", FD_SETSIZE);
clean_header_list(list);
return ASYNC_NO_IO;
}
handle = curl_easy_init();
if (!handle) {
LM_ERR("Init curl handle failed!\n");
clean_header_list(list);
return ASYNC_NO_IO;
}
w_curl_easy_setopt(handle, CURLOPT_URL, url);
switch (method) {
case REST_CLIENT_POST:
w_curl_easy_setopt(handle, CURLOPT_POST, 1);
w_curl_easy_setopt(handle, CURLOPT_POSTFIELDS, req_body);
if (req_ctype) {
sprintf(print_buff, "Content-Type: %s", req_ctype);
list = curl_slist_append(list, print_buff);
w_curl_easy_setopt(handle, CURLOPT_HTTPHEADER, list);
}
break;
case REST_CLIENT_PUT:
w_curl_easy_setopt(handle, CURLOPT_PUT, 1);
w_curl_easy_setopt(handle, CURLOPT_POSTFIELDS, req_body);
if (req_ctype) {
sprintf(print_buff, "Content-Type: %s", req_ctype);
list = curl_slist_append(list, print_buff);
w_curl_easy_setopt(handle, CURLOPT_HTTPHEADER, list);
}
break;
case REST_CLIENT_GET:
break;
default:
LM_ERR("Unsupported rest_client_method: %d, defaulting to
GET\n", method);
}
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_FAILONERROR, 1);
w_curl_easy_setopt(handle, CURLOPT_STDERR, stdout);
w_curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_func);
w_curl_easy_setopt(handle, CURLOPT_WRITEDATA, body);
if (ctype) {
w_curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, header_func);
w_curl_easy_setopt(handle, CURLOPT_HEADERDATA, ctype);
}
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);
curl_multi_add_handle(multi_handle, handle);
timeout = connection_timeout_ms;
/* obtain a read fd in "connection_timeout" seconds at worst */
for (timeout = connection_timeout_ms; timeout > 0; timeout -=
busy_wait) {
mrc = curl_multi_perform(multi_handle, &running_handles);
if (mrc != CURLM_OK) {
LM_ERR("curl_multi_perform: %s\n",
curl_multi_strerror(mrc));
goto error;
}
mrc = curl_multi_timeout(multi_handle, &retry_time);
if (mrc != CURLM_OK) {
LM_ERR("curl_multi_timeout: %s\n",
curl_multi_strerror(mrc));
goto error;
}
if (retry_time == -1) {
LM_INFO("curl_multi_timeout() returned -1, pausing
%ldms...\n",
sleep_on_bad_timeout);
busy_wait = sleep_on_bad_timeout;
usleep(1000UL * busy_wait);
continue;
}
busy_wait = retry_time < timeout ? retry_time : timeout;
/**
* libcurl is currently stuck in internal operations (connect)
* we have to wait a bit until we receive a read fd
*/
for (i = 0; i < busy_wait; i += check_time) {
/* transfer may have already been completed!! */
while ((cmsg = curl_multi_info_read(multi_handle,
&msgs_in_queue))) {
if (cmsg->easy_handle == handle && cmsg->msg ==
CURLMSG_DONE) {
LM_DBG("done, no need for async!\n");
clean_header_list(list);
*out_handle = handle;
return ASYNC_SYNC;
}
}
FD_ZERO(&rset);
mrc = curl_multi_fdset(multi_handle, &rset, &wset,
&eset, &max_fd);
if (mrc != CURLM_OK) {
LM_ERR("curl_multi_fdset: %s\n",
curl_multi_strerror(mrc));
goto error;
}
if (max_fd != -1) {
for (fd = 0; fd <= max_fd; fd++) {
if (FD_ISSET(fd, &rset)) {
LM_DBG(" >>>>>>>>>> fd %d
ISSET(read)\n", fd);
if (is_new_transfer(fd)) {
LM_DBG("add fd to read
list: %d\n", fd);
add_transfer(fd);
goto success;
}
}
}
}
usleep(1000UL * check_time);
}
}
LM_ERR("timeout while connecting to '%s' (%ld sec)\n", url,
connection_timeout);
goto error;
success:
clean_header_list(list);
*out_handle = handle;
return fd;
error:
mrc = curl_multi_remove_handle(multi_handle, handle);
if (mrc != CURLM_OK)
LM_ERR("curl_multi_remove_handle: %s\n",
curl_multi_strerror(mrc));
cleanup:
clean_header_list(list);
curl_easy_cleanup(handle);
return ASYNC_NO_IO;
}
/**
* rest_put_method - performs an HTTP POST 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)
{
LM_INFO("URL : %s", url);
CURLcode rc;
CURL *handle = NULL;
long http_rc;
struct curl_slist *list = NULL;
str st = { 0, 0 };
str res_body = { NULL, 0 }, tbody;
str dst_uri = { 0, 0 };
pv_value_t pv_val;
char reqbody[1000] = "";
char temp_buff[1000] = "";
char resturl[1000] = "";
char *fromuri=NULL, *touri=NULL, *instanceId=NULL;
int randValue=0;
char *temp_str = NULL;
handle = curl_easy_init();
if (!handle) {
LM_ERR("Init curl handle failed!\n");
return -1;
}
char Body[1000] = "";
sprintf(Body, "%s", body);
char Ctype[1000] = "";
sprintf(Ctype, "%s", ctype);
fromuri = strtok(Body, ",");
touri = strtok(NULL, ",");
instanceId = strtok(NULL, ",");
temp_str = "trace-id=";
char *xtrace = (char*)malloc(1+strlen(temp_str)+strlen(instanceId));
strcpy(xtrace,temp_str);
strcat(xtrace,instanceId);
if (ctype) {
sprintf(temp_buff, "Content-Type: %s", Ctype);
list = curl_slist_append(list, temp_buff);
sprintf(temp_buff, "Uid: %s", &fromuri[2]);
list = curl_slist_append(list, temp_buff);
sprintf(temp_buff, "serviceId: tel");
list = curl_slist_append(list, temp_buff);
sprintf(temp_buff, "custguid: %s", instanceId);
list = curl_slist_append(list, temp_buff);
randValue = generateRandomNumber();
sprintf(temp_buff, "x-tracking-id: %d", randValue );
list = curl_slist_append(list, temp_buff);
sprintf(temp_buff, "X-Trace: %s", xtrace );
list = curl_slist_append(list, temp_buff);
list = curl_slist_append(list, "x-server-name: RTCGSM");
list = curl_slist_append(list, "x-client-name: IMS");
list = curl_slist_append(list, "x-source-id: OpenSIP");
list = curl_slist_append(list, "user-agent: OpenSIPv1.11.3");
sprintf(temp_buff, "device-id: %s", instanceId );
list = curl_slist_append(list, temp_buff);
w_curl_easy_setopt(handle, CURLOPT_HTTPHEADER, list);
}
sprintf(resturl, "%suid=%s&custguid=%s", url, &fromuri[2], instanceId);
LM_INFO("**fromuri: %s, touri: %s, instanceId: %s, Xtrace: %s, REST
request url: %s", &fromuri[2], &touri[2], instanceId,
xtrace,resturl);
w_curl_easy_setopt(handle, CURLOPT_URL, resturl);
w_curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "PUT");
/*Populating request payload*/
sprintf(reqbody,
"{\"participantsInfo\":[\"%s\"],\"callType\":\"audio\",\"instanceId\":\"%s\",\"fromUID\":\"%s\",\"fromTN\":\"%s\",\"isOpenSipRequest\":%s,\"displayName\":\"Call
From
IMS\",\"deviceType\":\"Android/iOS/STB/IMS\"}",&touri[2],instanceId,&fromuri[2],&fromuri[2],"true");
LM_INFO("*Actual rest request payload (JSON):jsonPayload=
%s\n",reqbody);
w_curl_easy_setopt(handle, CURLOPT_POSTFIELDS, reqbody);
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(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;
LM_INFO("*: Actual result body is: jsonPayload= %s\n", res_body.s);
char tempstring[1000] = "";
sprintf(tempstring, "%s", res_body.s);
char *token = NULL;
char respstring[1000] = "";
sprintf(respstring, "%s", res_body.s);
token = NULL;
token = strtok(respstring, ",");
token = strtok(NULL, ",");
token = strtok(NULL, ",");
char mucAndJigassi[1000] = "";
char muc[1000] = "";
char jigasiIp[1000] = "";
char jigasiFQDN[1000] = "";
sprintf(mucAndJigassi, "%s", token);
token = NULL;
token = strtok(&mucAndJigassi[9], "@");
sprintf(muc, "%s", token);
token = strtok(NULL, "@");
token = strtok(token, "\"");
sprintf(jigasiIp, "%s", token);
sprintf(jigasiFQDN, "sip:%s:5060", jigasiIp);
dst_uri.s = jigasiFQDN;
dst_uri.len = strlen(dst_uri.s);
if (set_dst_uri(msg, &dst_uri) < 0) {
LM_ERR("error while setting dst uri\n");
goto cleanup;
}
sprintf(pv_val.rs.s, "%s", muc);
pv_val.rs.len = strlen(pv_val.rs.s);
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:
clean_header_list(list);
curl_easy_cleanup(handle);
return -1;
}
/*
* Copyright (C) 2013 OpenSIPS Solutions
*
* This file is part of opensips, a free SIP server.
*
* opensips 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 2 of the License, or
* (at your option) any later version
*
* opensips 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* History:
* -------
* 2013-02-28: Created (Liviu)
*/
#ifndef _REST_METHODS_
#define _REST_METHODS_
#include "../../pvar.h"
#include "../../dprint.h"
#include "../../error.h"
#include "../../mem/mem.h"
extern CURLM *multi_handle;
extern long connection_timeout;
extern long connection_timeout_ms;
extern long curl_timeout;
extern char *ssl_capath;
extern int ssl_verifypeer;
extern int ssl_verifyhost;
/* Currently supported HTTP verbs */
enum rest_client_method {
REST_CLIENT_GET,
REST_CLIENT_POST,
REST_CLIENT_PUT
};
typedef struct rest_async_param_ {
enum rest_client_method method;
CURL *handle;
str body;
str ctype;
pv_spec_p body_pv;
pv_spec_p ctype_pv;
pv_spec_p code_pv;
} rest_async_param;
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,
CURL **out_handle, str *body, str
*ctype);
enum async_ret_code resume_async_http_req(int fd, struct sip_msg *msg, void
*param);
#endif /* _REST_METHODS_ */
_______________________________________________
Users mailing list
[email protected]
http://lists.opensips.org/cgi-bin/mailman/listinfo/users