Skip to content

Commit 3483af7

Browse files
TELECOM-11880: Implementing curl_share locking
1 parent 3e3a3c8 commit 3483af7

File tree

2 files changed

+67
-28
lines changed

2 files changed

+67
-28
lines changed

modules/rest_client/rest_client.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,11 +1040,6 @@ int async_rest_method_v2(enum rest_client_method method, struct sip_msg *msg,
10401040

10411041
async_status = read_fd;
10421042
return 1;
1043-
1044-
done:
1045-
if (lrc == RCL_OK_LOCKED)
1046-
rcl_release_url(host, rc == RCL_OK);
1047-
return rc;
10481043
}
10491044

10501045
static int w_async_rest_get_v2(struct sip_msg *msg, async_ctx *ctx, str *url,

modules/rest_client/rest_methods.c

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "../../trace_api.h"
3636
#include "../../resolve.h"
3737
#include "../../timer.h"
38+
#include "../../lock_ops.h"
3839

3940
#include "../tls_mgm/api.h"
4041

@@ -89,6 +90,10 @@ extern trace_proto_t tprot;
8990
extern char *rest_id_s;
9091

9192
static CURLSH *curl_share = NULL;
93+
static gen_lock_t curl_share_locks[CURL_LOCK_DATA_LAST];
94+
95+
static enum curl_status status;
96+
static long timer;
9297

9398
/**
9499
* We cannot use the "parallel transfers" feature of libcurl's multi interface
@@ -179,9 +184,18 @@ int rcl_init_internals(void)
179184

180185
#define w_curl_multi_setopt(mh, opt, value) \
181186
do { \
182-
rc = curl_multi_setopt(mh, opt, value); \
183-
if (rc != CURLE_OK) { \
184-
LM_ERR("curl_multi_setopt(%d): (%s)\n", opt, curl_easy_strerror(rc)); \
187+
mrc = curl_multi_setopt(mh, opt, value); \
188+
if (mrc != CURLE_OK) { \
189+
LM_ERR("curl_multi_setopt(%d): (%s)\n", opt, curl_multi_strerror(mrc)); \
190+
goto cleanup; \
191+
} \
192+
} while (0)
193+
194+
#define w_curl_share_setopt(cs, opt, value) \
195+
do { \
196+
src = curl_share_setopt(cs, opt, value); \
197+
if (src != CURLE_OK) { \
198+
LM_ERR("curl_share_setopt: %s\n", curl_share_strerror(src)); \
185199
goto cleanup; \
186200
} \
187201
} while (0)
@@ -426,21 +440,40 @@ static inline int get_easy_status(CURL *handle, CURLM *multi, CURLcode *code)
426440
return -1;
427441
}
428442

443+
static void libcurl_share_lock(CURL *handle, curl_lock_data data, curl_lock_access access, void *clientp) {
444+
LM_DBG("Locking libcurl share %d\n", data);
445+
lock_get(&curl_share_locks[data]);
446+
}
447+
448+
static void libcurl_share_unlock(CURL *handle, curl_lock_data data, void *clientp) {
449+
LM_DBG("Unlocking libcurl share %d\n", data);
450+
lock_release(&curl_share_locks[data]);
451+
}
452+
429453
static CURLSH *get_curl_share(void) {
430454
CURLSHcode src;
431455

432456
if (!curl_share) {
433-
curl_share = curl_share_init();
457+
for (int i =0; i < CURL_LOCK_DATA_LAST; ++i) {
458+
lock_init(&curl_share_locks[i]);
459+
}
434460

435-
src = curl_share_setopt(curl_share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
461+
curl_share = curl_share_init();
436462

437-
if (src != CURLSHE_OK) {
438-
LM_WARN("curl_share_setopt: %s\n", curl_share_strerror(src));
439-
return NULL;
440-
}
463+
w_curl_share_setopt(curl_share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
464+
w_curl_share_setopt(curl_share, CURLSHOPT_LOCKFUNC, libcurl_share_lock);
465+
w_curl_share_setopt(curl_share, CURLSHOPT_UNLOCKFUNC, libcurl_share_unlock);
441466
}
442467

443468
return curl_share;
469+
cleanup:
470+
for (int i =0; i < CURL_LOCK_DATA_LAST; ++i) {
471+
lock_destroy(&curl_share_locks[i]);
472+
}
473+
474+
curl_share_cleanup(curl_share);
475+
curl_share = NULL;
476+
return NULL;
444477
}
445478

446479
static int init_transfer(CURL *handle, char *url, unsigned long timeout_s)
@@ -466,8 +499,7 @@ static int init_transfer(CURL *handle, char *url, unsigned long timeout_s)
466499
w_curl_easy_setopt(handle, CURLOPT_VERBOSE, 1);
467500
w_curl_easy_setopt(handle, CURLOPT_FAILONERROR, 0);
468501

469-
if (is_printable(L_DBG))
470-
w_curl_easy_setopt(handle, CURLOPT_STDERR, stderr);
502+
w_curl_easy_setopt(handle, CURLOPT_STDERR, stdout);
471503

472504
if (ssl_capath)
473505
w_curl_easy_setopt(handle, CURLOPT_CAPATH, ssl_capath);
@@ -487,12 +519,15 @@ static int init_transfer(CURL *handle, char *url, unsigned long timeout_s)
487519
static int init_socket_keepalive(CURL *handle) {
488520
CURLcode rc;
489521

490-
curl_share = get_curl_share();
491-
w_curl_easy_setopt(handle, CURLOPT_SHARE, curl_share);
522+
if (share_connections) {
523+
// If the share cannot be created then log warn but keep going
524+
curl_share = get_curl_share();
525+
w_curl_easy_setopt(handle, CURLOPT_SHARE, curl_share);
526+
}
492527

493528
w_curl_easy_setopt(handle, CURLOPT_TCP_KEEPALIVE, 1L);
494-
w_curl_easy_setopt(handle, CURLOPT_TCP_KEEPIDLE, 5L);
495-
w_curl_easy_setopt(handle, CURLOPT_TCP_KEEPINTVL, 5L);
529+
w_curl_easy_setopt(handle, CURLOPT_TCP_KEEPIDLE, 180L);
530+
w_curl_easy_setopt(handle, CURLOPT_TCP_KEEPINTVL, 180L);
496531
w_curl_easy_setopt(handle, CURLOPT_MAXAGE_CONN, socket_keep_alive);
497532

498533
return 0;
@@ -1290,6 +1325,9 @@ static enum async_ret_code _resume_async_http_req_v2(int fd, struct sip_msg *msg
12901325
goto cleanup;
12911326
}
12921327

1328+
w_curl_multi_setopt(multi_handle, CURLMOPT_TIMERFUNCTION, timer_cb);
1329+
w_curl_multi_setopt(multi_handle, CURLMOPT_TIMERDATA, &timer);
1330+
12931331
retr = 0;
12941332
do {
12951333
/* When @enable_expect_100 is on, both the client body upload and the
@@ -1686,8 +1724,7 @@ int start_async_http_req_v2(struct sip_msg *msg, enum rest_client_method method,
16861724
CURLMcode mrc;
16871725
OSS_CURLM *multi_list;
16881726
CURLM *multi_handle;
1689-
long busy_wait, timeout, connect_timeout, retry_time, timer;
1690-
enum curl_status status = CURL_NONE;
1727+
long busy_wait, timeout, connect_timeout, retry_time;
16911728

16921729
handle = curl_easy_init();
16931730

@@ -1722,10 +1759,7 @@ int start_async_http_req_v2(struct sip_msg *msg, enum rest_client_method method,
17221759
w_curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_func);
17231760
w_curl_easy_setopt(handle, CURLOPT_WRITEDATA, body);
17241761

1725-
if (share_connections) {
1726-
// If the share cannot be created then log warn but keep going
1727-
init_socket_keepalive(handle);
1728-
}
1762+
init_socket_keepalive(handle);
17291763

17301764
if (ctype) {
17311765
w_curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, header_func);
@@ -1761,6 +1795,7 @@ int start_async_http_req_v2(struct sip_msg *msg, enum rest_client_method method,
17611795

17621796
w_curl_multi_setopt(multi_handle, CURLMOPT_MAXCONNECTS, (long) max_connections);
17631797

1798+
status = CURL_NONE;
17641799
w_curl_easy_setopt(handle, CURLOPT_PREREQFUNCTION, prereq_callback);
17651800
w_curl_easy_setopt(handle, CURLOPT_PREREQDATA, &status);
17661801

@@ -1779,6 +1814,10 @@ int start_async_http_req_v2(struct sip_msg *msg, enum rest_client_method method,
17791814
do {
17801815
running_handles = run_multi_socket(multi_handle);
17811816

1817+
if (running_handles < 0) {
1818+
goto error;
1819+
}
1820+
17821821
if (status == CURL_REQUEST_SENT) {
17831822
goto success;
17841823
}
@@ -1797,9 +1836,14 @@ int start_async_http_req_v2(struct sip_msg *msg, enum rest_client_method method,
17971836
success:
17981837
async_parm->header_list = header_list;
17991838
async_parm->handle = handle;
1800-
async_parm->multi_list = multi_list;
18011839
header_list = NULL;
18021840
*out_fd = get_max_fd(ASYNC_SYNC); // Running only one socket at a time so it's always the max
1841+
1842+
if (*out_fd >= 0) {
1843+
async_parm->multi_list = multi_list;
1844+
} else {
1845+
put_multi(multi_list);
1846+
}
18031847
return RCL_OK;
18041848

18051849
error:
@@ -1875,4 +1919,4 @@ enum async_ret_code resume_async_http_req_v2(int fd, struct sip_msg *msg, void *
18751919

18761920
enum async_ret_code time_out_async_http_req_v2(int fd, struct sip_msg *msg, void *_param) {
18771921
return _resume_async_http_req_v2(fd, msg, (rest_async_param *)_param, 1);
1878-
}
1922+
}

0 commit comments

Comments
 (0)