@@ -90,9 +90,8 @@ extern trace_proto_t tprot;
9090extern char * rest_id_s ;
9191
9292static CURLSH * curl_share = NULL ;
93- static gen_lock_t curl_share_locks [ CURL_LOCK_DATA_LAST ] ;
93+ static gen_lock_t * curl_socket_lock = NULL ;
9494
95- static enum curl_status status ;
9695static long timer ;
9796
9897/**
@@ -441,23 +440,31 @@ static inline int get_easy_status(CURL *handle, CURLM *multi, CURLcode *code)
441440}
442441
443442static 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 ]);
443+ if (data == CURL_LOCK_DATA_CONNECT ) {
444+ LM_DBG ("Locking libcurl share %d\n" , data );
445+ lock_get (curl_socket_lock );
446+ }
446447}
447448
448449static 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 ]);
450+ if (data == CURL_LOCK_DATA_CONNECT ) {
451+ LM_DBG ("Unlocking libcurl share %d\n" , data );
452+ lock_release (curl_socket_lock );
453+ }
451454}
452455
453456static CURLSH * get_curl_share (void ) {
454457 CURLSHcode src ;
455458
456459 if (!curl_share ) {
457- for (int i = 0 ; i < CURL_LOCK_DATA_LAST ; ++ i ) {
458- lock_init (& curl_share_locks [i ]);
460+ curl_socket_lock = lock_alloc ();
461+
462+ if (!curl_socket_lock ) {
463+ goto done ;
459464 }
460465
466+ lock_init (curl_socket_lock );
467+
461468 curl_share = curl_share_init ();
462469
463470 w_curl_share_setopt (curl_share , CURLSHOPT_SHARE , CURL_LOCK_DATA_CONNECT );
@@ -467,16 +474,19 @@ static CURLSH *get_curl_share(void) {
467474
468475 return curl_share ;
469476cleanup :
470- for (int i = 0 ; i < CURL_LOCK_DATA_LAST ; ++ i ) {
471- lock_destroy (& curl_share_locks [i ]);
477+ if (curl_socket_lock ) {
478+ lock_destroy (curl_socket_lock );
479+ lock_dealloc (curl_socket_lock );
480+ curl_socket_lock = NULL ;
472481 }
473482
474- curl_share_cleanup (curl_share );
483+ curl_share_cleanup (curl_share ); // Passing NULL returns early if init failed
475484 curl_share = NULL ;
485+ done :
476486 return NULL ;
477487}
478488
479- static int init_transfer (CURL * handle , char * url , unsigned long timeout_s )
489+ static int init_transfer (CURL * handle , char * url , unsigned long connect_timeout_s , unsigned long timeout_s )
480490{
481491 CURLcode rc ;
482492
@@ -491,10 +501,8 @@ static int init_transfer(CURL *handle, char *url, unsigned long timeout_s)
491501 tls_dom = NULL ;
492502 }
493503
494- w_curl_easy_setopt (handle , CURLOPT_CONNECTTIMEOUT ,
495- timeout_s && timeout_s > connection_timeout ? timeout_s : connection_timeout );
496- w_curl_easy_setopt (handle , CURLOPT_TIMEOUT ,
497- timeout_s && timeout_s > curl_timeout ? timeout_s : curl_timeout );
504+ w_curl_easy_setopt (handle , CURLOPT_CONNECTTIMEOUT , connect_timeout_s );
505+ w_curl_easy_setopt (handle , CURLOPT_TIMEOUT , timeout_s );
498506
499507 w_curl_easy_setopt (handle , CURLOPT_VERBOSE , 1 );
500508 w_curl_easy_setopt (handle , CURLOPT_FAILONERROR , 0 );
@@ -802,7 +810,7 @@ int rest_sync_transfer(enum rest_client_method method, struct sip_msg *msg,
802810 str st = STR_NULL , res_body = STR_NULL , tbody , ttype ;
803811
804812 curl_easy_reset (sync_handle );
805- if (init_transfer (sync_handle , url , 0 ) != 0 ) {
813+ if (init_transfer (sync_handle , url , connection_timeout , curl_timeout ) != 0 ) {
806814 LM_ERR ("failed to init transfer to %s\n" , url );
807815 goto cleanup ;
808816 }
@@ -902,7 +910,7 @@ static int start_async_http_req_v1(struct sip_msg *msg, enum rest_client_method
902910 CURLMcode mrc ;
903911 fd_set rset , wset , eset ;
904912 int max_fd , fd , http_rc , ret = RCL_INTERNAL_ERR ;
905- long busy_wait , timeout , connect_timeout ;
913+ long busy_wait , timeout ;
906914 long retry_time ;
907915 OSS_CURLM * multi_list ;
908916 CURLM * multi_handle ;
@@ -918,7 +926,7 @@ static int start_async_http_req_v1(struct sip_msg *msg, enum rest_client_method
918926 goto cleanup ;
919927 }
920928
921- if (init_transfer (handle , url , async_parm -> timeout_s ) != 0 ) {
929+ if (init_transfer (handle , url , connection_timeout , curl_timeout ) != 0 ) {
922930 LM_ERR ("failed to init transfer to %s\n" , url );
923931 goto cleanup ;
924932 }
@@ -972,27 +980,18 @@ static int start_async_http_req_v1(struct sip_msg *msg, enum rest_client_method
972980 multi_handle = multi_list -> multi_handle ;
973981 curl_multi_add_handle (multi_handle , handle );
974982
975- connect_timeout = (async_parm -> timeout_s * 1000 ) > connection_timeout_ms ?
976- (async_parm -> timeout_s * 1000 ) : connection_timeout_ms ;
977- timeout = connect_timeout ;
983+ timeout = connection_timeout_ms ;
978984 busy_wait = connect_poll_interval ;
979985
980986 /* obtain a read fd in "connection_timeout" seconds at worst */
981- for (timeout = connect_timeout ; timeout > 0 ; timeout -= busy_wait ) {
982- double connect = -1 ;
983- long req_sz = -1 ;
984-
987+ for (timeout = connection_timeout_ms ; timeout > 0 ; timeout -= busy_wait ) {
985988 mrc = curl_multi_perform (multi_handle , & running_handles );
986989 if (mrc != CURLM_OK && mrc != CURLM_CALL_MULTI_PERFORM ) {
987990 LM_ERR ("curl_multi_perform: %s\n" , curl_multi_strerror (mrc ));
988991 goto error ;
989992 }
990993
991- curl_easy_getinfo (handle , CURLINFO_CONNECT_TIME , & connect );
992- curl_easy_getinfo (handle , CURLINFO_REQUEST_SIZE , & req_sz );
993-
994- LM_DBG ("perform code: %d, handles: %d, connect: %.3lfs, reqsz: %ldB\n" ,
995- mrc , running_handles , connect , req_sz );
994+ LM_DBG ("perform code: %d, handles: %d\n" , mrc , running_handles );
996995
997996 /* transfer completed! But how well? */
998997 if (running_handles == 0 ) {
@@ -1015,8 +1014,8 @@ static int start_async_http_req_v1(struct sip_msg *msg, enum rest_client_method
10151014
10161015 case CURLE_OPERATION_TIMEDOUT :
10171016 if (http_rc == 0 ) {
1018- LM_ERR ("connect timeout on %s (%ldms )\n" , url ,
1019- connect_timeout );
1017+ LM_ERR ("connect timeout on %s (%lds )\n" , url ,
1018+ connection_timeout );
10201019 ret = RCL_CONNECT_TIMEOUT ;
10211020 goto error ;
10221021 }
@@ -1055,7 +1054,7 @@ static int start_async_http_req_v1(struct sip_msg *msg, enum rest_client_method
10551054 for (fd = 0 ; fd <= max_fd ; fd ++ ) {
10561055 if (FD_ISSET (fd , & rset )) {
10571056 LM_DBG ("ongoing transfer on fd %d\n" , fd );
1058- if (req_sz > 0 && is_new_transfer (fd )) {
1057+ if (is_new_transfer (fd )) {
10591058 LM_DBG (">>> add fd %d to ongoing transfers\n" , fd );
10601059 add_transfer (fd );
10611060 goto success ;
@@ -1072,7 +1071,7 @@ static int start_async_http_req_v1(struct sip_msg *msg, enum rest_client_method
10721071
10731072 LM_DBG ("libcurl TCP connect: we should wait up to %ldms "
10741073 "(timeout=%ldms, poll=%ldms)!\n" , retry_time ,
1075- connect_timeout , connect_poll_interval );
1074+ connection_timeout_ms , connect_poll_interval );
10761075
10771076 /*
10781077 from curl_multi_timeout() docs:
@@ -1146,8 +1145,8 @@ static enum async_ret_code _resume_async_http_req(int fd, struct sip_msg *msg,
11461145 if (timed_out ) {
11471146 char * url = NULL ;
11481147 curl_easy_getinfo (param -> handle , CURLINFO_EFFECTIVE_URL , & url );
1149- LM_ERR ("async %s timed out, URL: %s (timeout: %lds) \n" ,
1150- rest_client_method_str (param -> method ), url , param -> timeout_s );
1148+ LM_ERR ("async %s timed out, URL: %s\n" ,
1149+ rest_client_method_str (param -> method ), url );
11511150 goto cleanup ;
11521151 }
11531152
@@ -1160,10 +1159,7 @@ static enum async_ret_code _resume_async_http_req(int fd, struct sip_msg *msg,
11601159 LM_DBG ("perform result: %d, running: %d (break: %d)\n" , mrc , running ,
11611160 mrc != CURLM_CALL_MULTI_PERFORM && (mrc != CURLM_OK || !running ));
11621161
1163- if (mrc == CURLM_OK ) {
1164- if (!running )
1165- break ;
1166-
1162+ if (mrc == CURLM_OK && running ) {
11671163 async_status = ASYNC_CONTINUE ;
11681164 return 1 ;
11691165 /* this rc has been removed since cURL 7.20.0 (Feb 2010), but it's not
@@ -1613,10 +1609,9 @@ int connect_only(preconnect_urls *precon_urls, int total_cons) {
16131609 long busy_wait , timer ;
16141610 int msgq , num_of_connections , exit_code = 0 ;
16151611
1616- curl_share = get_curl_share ();
1617-
1618- if (!curl_share ) {
1619- goto cleanup ;
1612+ if (!share_connections ) {
1613+ exit_code = -1 ;
1614+ goto done ;
16201615 }
16211616
16221617 multi_list = get_multi ();
@@ -1638,7 +1633,7 @@ int connect_only(preconnect_urls *precon_urls, int total_cons) {
16381633 handle = curl_easy_init ();
16391634 curl_multi_add_handle (multi_handle , handle );
16401635
1641- if (init_transfer (handle , url , 0 ) != 0 ) {
1636+ if (init_transfer (handle , url , curl_timeout , curl_timeout ) != 0 ) {
16421637 exit_code = -1 ;
16431638 goto cleanup ;
16441639 }
@@ -1649,7 +1644,6 @@ int connect_only(preconnect_urls *precon_urls, int total_cons) {
16491644 }
16501645
16511646 w_curl_easy_setopt (handle , CURLOPT_NOBODY , 1L );
1652- w_curl_easy_setopt (handle , CURLOPT_SHARE , curl_share );
16531647 }
16541648
16551649 start = start -> next ;
@@ -1724,7 +1718,7 @@ int start_async_http_req_v2(struct sip_msg *msg, enum rest_client_method method,
17241718 CURLMcode mrc ;
17251719 OSS_CURLM * multi_list ;
17261720 CURLM * multi_handle ;
1727- long busy_wait , connect_timeout ;
1721+ long busy_wait , req_sz ;
17281722
17291723 handle = curl_easy_init ();
17301724
@@ -1733,7 +1727,7 @@ int start_async_http_req_v2(struct sip_msg *msg, enum rest_client_method method,
17331727 goto cleanup ;
17341728 }
17351729
1736- if (init_transfer (handle , url , async_parm -> timeout_s ) != 0 ) {
1730+ if (init_transfer (handle , url , connection_timeout , async_parm -> timeout_s ) != 0 ) {
17371731 LM_ERR ("failed to init transfer to %s\n" , url );
17381732 goto cleanup ;
17391733 }
@@ -1793,15 +1787,8 @@ int start_async_http_req_v2(struct sip_msg *msg, enum rest_client_method method,
17931787 goto cleanup ;
17941788 }
17951789
1796- w_curl_multi_setopt (multi_handle , CURLMOPT_MAXCONNECTS , (long ) max_connections );
1797-
1798- status = CURL_NONE ;
1799- w_curl_easy_setopt (handle , CURLOPT_PREREQFUNCTION , prereq_callback );
1800- w_curl_easy_setopt (handle , CURLOPT_PREREQDATA , & status );
1801-
1802- connect_timeout = (async_parm -> timeout_s * 1000 ) > connection_timeout_ms ?
1803- (async_parm -> timeout_s * 1000 ) : connection_timeout_ms ;
1804- busy_wait = connect_poll_interval ;
1790+ w_curl_multi_setopt (multi_handle , CURLMOPT_MAX_HOST_CONNECTIONS , max_host_connections );
1791+ w_curl_multi_setopt (multi_handle , CURLMOPT_MAXCONNECTS , max_connections );
18051792
18061793 w_curl_multi_setopt (multi_handle , CURLMOPT_TIMERFUNCTION , timer_cb );
18071794 w_curl_multi_setopt (multi_handle , CURLMOPT_TIMERDATA , & timer );
@@ -1810,14 +1797,18 @@ int start_async_http_req_v2(struct sip_msg *msg, enum rest_client_method method,
18101797 goto cleanup ;
18111798 }
18121799
1800+ busy_wait = connect_poll_interval ;
1801+
18131802 do {
18141803 running_handles = run_multi_socket (multi_handle );
18151804
18161805 if (running_handles < 0 ) {
18171806 goto error ;
18181807 }
18191808
1820- if (status == CURL_REQUEST_SENT ) {
1809+ curl_easy_getinfo (handle , CURLINFO_REQUEST_SIZE , & req_sz );
1810+
1811+ if (req_sz > 0 ) {
18211812 goto success ;
18221813 }
18231814
0 commit comments