@@ -399,7 +399,7 @@ static inline int get_easy_status(CURL *handle, CURLM *multi, CURLcode *code)
399399 return -1 ;
400400}
401401
402- static int init_transfer (CURL * handle , char * url )
402+ static int init_transfer (CURL * handle , char * url , unsigned long timeout_s )
403403{
404404 CURLcode rc ;
405405
@@ -414,8 +414,10 @@ static int init_transfer(CURL *handle, char *url)
414414 tls_dom = NULL ;
415415 }
416416
417- w_curl_easy_setopt (handle , CURLOPT_CONNECTTIMEOUT , connection_timeout );
418- w_curl_easy_setopt (handle , CURLOPT_TIMEOUT , curl_timeout );
417+ w_curl_easy_setopt (handle , CURLOPT_CONNECTTIMEOUT ,
418+ timeout_s && timeout_s < connection_timeout ? timeout_s : connection_timeout );
419+ w_curl_easy_setopt (handle , CURLOPT_TIMEOUT ,
420+ timeout_s && timeout_s < curl_timeout ? timeout_s : curl_timeout );
419421
420422 w_curl_easy_setopt (handle , CURLOPT_VERBOSE , 1 );
421423 w_curl_easy_setopt (handle , CURLOPT_STDERR , stdout );
@@ -702,7 +704,7 @@ int rest_sync_transfer(enum rest_client_method method, struct sip_msg *msg,
702704 str st = STR_NULL , res_body = STR_NULL , tbody , ttype ;
703705
704706 curl_easy_reset (sync_handle );
705- if (init_transfer (sync_handle , url ) != 0 ) {
707+ if (init_transfer (sync_handle , url , 0 ) != 0 ) {
706708 LM_ERR ("failed to init transfer to %s\n" , url );
707709 goto cleanup ;
708710 }
@@ -802,7 +804,7 @@ int rest_sync_transfer(enum rest_client_method method, struct sip_msg *msg,
802804 * @url: HTTP URL to be queried
803805 * @req_body: Body of the request (NULL if not needed)
804806 * @req_ctype: Value for the "Content-Type: " header of the request (same as ^)
805- * @async_parm: output param, will contain async handles
807+ * @async_parm: in/out param, will contain async handles
806808 * @body: reply body; gradually reallocated as data arrives
807809 * @ctype: will eventually hold the last "Content-Type" header of the reply
808810 * @out_fd: the fd to poll on, or a negative error code
@@ -819,7 +821,7 @@ int start_async_http_req(struct sip_msg *msg, enum rest_client_method method,
819821 CURLMcode mrc ;
820822 fd_set rset , wset , eset ;
821823 int max_fd , fd , http_rc , ret = RCL_INTERNAL_ERR ;
822- long busy_wait , timeout ;
824+ long busy_wait , timeout , connect_timeout ;
823825 long retry_time ;
824826 OSS_CURLM * multi_list ;
825827 CURLM * multi_handle ;
@@ -835,7 +837,7 @@ int start_async_http_req(struct sip_msg *msg, enum rest_client_method method,
835837 goto cleanup ;
836838 }
837839
838- if (init_transfer (handle , url ) != 0 ) {
840+ if (init_transfer (handle , url , async_parm -> timeout_s ) != 0 ) {
839841 LM_ERR ("failed to init transfer to %s\n" , url );
840842 goto cleanup ;
841843 }
@@ -889,18 +891,27 @@ int start_async_http_req(struct sip_msg *msg, enum rest_client_method method,
889891 multi_handle = multi_list -> multi_handle ;
890892 curl_multi_add_handle (multi_handle , handle );
891893
892- timeout = connection_timeout_ms ;
894+ connect_timeout = (async_parm -> timeout_s * 1000 ) < connection_timeout_ms ?
895+ (async_parm -> timeout_s * 1000 ) : connection_timeout_ms ;
896+ timeout = connect_timeout ;
893897 busy_wait = connect_poll_interval ;
894898
895899 /* obtain a read fd in "connection_timeout" seconds at worst */
896- for (timeout = connection_timeout_ms ; timeout > 0 ; timeout -= busy_wait ) {
900+ for (timeout = connect_timeout ; timeout > 0 ; timeout -= busy_wait ) {
901+ curl_off_t connect = -1 ;
902+ long req_sz = -1 ;
903+
897904 mrc = curl_multi_perform (multi_handle , & running_handles );
898905 if (mrc != CURLM_OK && mrc != CURLM_CALL_MULTI_PERFORM ) {
899906 LM_ERR ("curl_multi_perform: %s\n" , curl_multi_strerror (mrc ));
900907 goto error ;
901908 }
902909
903- LM_DBG ("perform code: %d, handles: %d\n" , mrc , running_handles );
910+ curl_easy_getinfo (handle , CURLINFO_CONNECT_TIME_T , & connect );
911+ curl_easy_getinfo (handle , CURLINFO_REQUEST_SIZE , & req_sz );
912+
913+ LM_DBG ("perform code: %d, handles: %d, connect: %ldµs, reqsz: %ldB\n" ,
914+ mrc , running_handles , connect , req_sz );
904915
905916 /* transfer completed! But how well? */
906917 if (running_handles == 0 ) {
@@ -923,8 +934,8 @@ int start_async_http_req(struct sip_msg *msg, enum rest_client_method method,
923934
924935 case CURLE_OPERATION_TIMEDOUT :
925936 if (http_rc == 0 ) {
926- LM_ERR ("connect timeout on %s (%lds )\n" , url ,
927- connection_timeout );
937+ LM_ERR ("connect timeout on %s (%ldms )\n" , url ,
938+ connect_timeout );
928939 ret = RCL_CONNECT_TIMEOUT ;
929940 goto error ;
930941 }
@@ -962,9 +973,8 @@ int start_async_http_req(struct sip_msg *msg, enum rest_client_method method,
962973 if (max_fd != -1 ) {
963974 for (fd = 0 ; fd <= max_fd ; fd ++ ) {
964975 if (FD_ISSET (fd , & rset )) {
965-
966976 LM_DBG ("ongoing transfer on fd %d\n" , fd );
967- if (is_new_transfer (fd )) {
977+ if (connect > 0 && req_sz > 0 && is_new_transfer (fd )) {
968978 LM_DBG (">>> add fd %d to ongoing transfers\n" , fd );
969979 add_transfer (fd );
970980 goto success ;
@@ -981,7 +991,7 @@ int start_async_http_req(struct sip_msg *msg, enum rest_client_method method,
981991
982992 LM_DBG ("libcurl TCP connect: we should wait up to %ldms "
983993 "(timeout=%ldms, poll=%ldms)!\n" , retry_time ,
984- connection_timeout_ms , connect_poll_interval );
994+ connect_timeout , connect_poll_interval );
985995
986996 /*
987997 from curl_multi_timeout() docs:
@@ -1055,8 +1065,8 @@ static enum async_ret_code _resume_async_http_req(int fd, struct sip_msg *msg,
10551065 if (timed_out ) {
10561066 char * url = NULL ;
10571067 curl_easy_getinfo (param -> handle , CURLINFO_EFFECTIVE_URL , & url );
1058- LM_ERR ("async %s timed out, URL: %s\n" ,
1059- rest_client_method_str (param -> method ), url );
1068+ LM_ERR ("async %s timed out, URL: %s (timeout: %lds) \n" ,
1069+ rest_client_method_str (param -> method ), url , param -> timeout_s );
10601070 goto cleanup ;
10611071 }
10621072
@@ -1069,10 +1079,12 @@ static enum async_ret_code _resume_async_http_req(int fd, struct sip_msg *msg,
10691079 LM_DBG ("perform result: %d, running: %d (break: %d)\n" , mrc , running ,
10701080 mrc != CURLM_CALL_MULTI_PERFORM && (mrc != CURLM_OK || !running ));
10711081
1072- if (mrc == CURLM_OK && running ) {
1082+ if (mrc == CURLM_OK ) {
1083+ if (!running )
1084+ break ;
1085+
10731086 async_status = ASYNC_CONTINUE ;
10741087 return 1 ;
1075-
10761088 /* this rc has been removed since cURL 7.20.0 (Feb 2010), but it's not
10771089 * yet marked as deprecated, so let's keep the do/while loop */
10781090 } else if (mrc != CURLM_CALL_MULTI_PERFORM ) {
0 commit comments