From 60663791e1861eddd94b8afcaffb631256804c34 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Tue, 7 Jan 2025 21:43:38 +0100 Subject: [PATCH] 2025-01-07 21:43 UTC+0100 Emanuele Zavallone (emanuele.zavallone gmail.com) * contrib/hbcurl/easy.c * contrib/hbcurl/hbcurl.ch + added multi interface implementation --- ChangeLog.txt | 5 + contrib/hbcurl/core.c | 216 +++++++++++++++++++++++++++++++++++++++ contrib/hbcurl/hbcurl.ch | 28 +++++ 3 files changed, 249 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index a86a9e39fa..226e43d112 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -7,6 +7,11 @@ Entries may not always be in chronological/commit order. See license at the end of file. */ +2025-01-07 21:43 UTC+0100 Emanuele Zavallone (emanuele.zavallone gmail.com) + * contrib/hbcurl/easy.c + * contrib/hbcurl/hbcurl.ch + + added multi interface implementation + 2025-01-07 12:24 UTC+0100 Aleksander Czajczynski (hb fki.pl) * src/common/hbver.c * indent cleanup diff --git a/contrib/hbcurl/core.c b/contrib/hbcurl/core.c index db09635a10..2982b19f43 100644 --- a/contrib/hbcurl/core.c +++ b/contrib/hbcurl/core.c @@ -2499,6 +2499,222 @@ HB_FUNC( CURL_GETDATE ) hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); } +/* Multi interface */ +/* ----------------- */ + +typedef struct _HB_CURLM +{ + CURLM * curlm; + +} HB_CURLM, * PHB_CURLM; + + +/* Constructor/Destructor */ +/* ---------------------- */ + +static void PHB_CURLM_free( PHB_CURLM hb_curlm ) +{ + curl_multi_cleanup( hb_curlm->curlm ); + hb_xfree( hb_curlm ); +} + +static PHB_CURLM PHB_CURLM_create( ) +{ + CURLM * curlm = curl_multi_init(); + + if( curlm ) + { + PHB_CURLM hb_curlm = ( PHB_CURLM ) hb_xgrab( sizeof( HB_CURLM ) ); + + memset( hb_curlm, 0, sizeof( HB_CURLM ) ); + hb_curlm->curlm = curlm; + + return hb_curlm; + } + else + return NULL; +} + +static HB_GARBAGE_FUNC( PHB_CURLM_release ) +{ + PHB_CURLM * hb_curlm_ptr = ( PHB_CURLM * ) Cargo; + + /* Check if pointer is not NULL to avoid multiple freeing */ + if( hb_curlm_ptr && *hb_curlm_ptr ) + { + /* Destroy the object */ + PHB_CURLM_free( *hb_curlm_ptr ); + *hb_curlm_ptr = NULL; + } +} + +static const HB_GC_FUNCS s_gcCURLMFuncs = +{ + PHB_CURLM_release, + hb_gcDummyMark +}; + +static void PHB_CURLM_ret() +{ + void ** ph = ( void ** ) hb_gcAllocate( sizeof( PHB_CURLM ), &s_gcCURLMFuncs ); + + *ph = PHB_CURLM_create( ); + + hb_retptrGC( ph ); +} + +static void * PHB_CURLM_is( int iParam ) +{ + return hb_parptrGC( &s_gcCURLMFuncs, iParam ); +} + +static PHB_CURLM PHB_CURLM_par( int iParam ) +{ + void ** ph = ( void ** ) hb_parptrGC( &s_gcCURLMFuncs, iParam ); + + return ph ? ( PHB_CURLM ) *ph : NULL; +} + +/* Harbour interface */ +/* ----------------- */ + + +HB_FUNC( CURL_MULTI_INIT ) +{ + PHB_CURLM_ret( ); +} + +HB_FUNC( CURL_MULTI_CLEANUP ) +{ + if( PHB_CURLM_is( 1 ) ) + { + void ** ph = ( void ** ) hb_parptrGC( &s_gcCURLMFuncs, 1 ); + + if( ph && *ph ) + { + /* Destroy the object */ + PHB_CURLM_free( ( PHB_CURLM ) *ph ); + *ph = NULL; + } + } + else + hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); +} + +HB_FUNC( CURL_MULTI_ADD_HANDLE ) +{ + if( PHB_CURLM_is( 1 ) && PHB_CURL_is( 2 ) ) + { + PHB_CURLM hb_curlm = PHB_CURLM_par( 1 ); + PHB_CURL hb_curl = PHB_CURL_par( 2 ); + + hb_retnl( hb_curlm && hb_curl ? ( long ) curl_multi_add_handle( hb_curlm->curlm, hb_curl->curl) : HB_CURLM_INTERNAL_ERROR ); + } + else + hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); +} + +HB_FUNC( CURL_MULTI_REMOVE_HANDLE ) +{ + if( PHB_CURLM_is( 1 ) && PHB_CURL_is( 2 ) ) + { + PHB_CURLM hb_curlm = PHB_CURLM_par( 1 ); + PHB_CURL hb_curl = PHB_CURL_par( 2 ); + + hb_retnl( hb_curlm && hb_curl ? ( long ) curl_multi_remove_handle( hb_curlm->curlm, hb_curl->curl) : HB_CURLM_INTERNAL_ERROR ); + } + else + hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); +} + +HB_FUNC( CURL_MULTI_PERFORM ) +{ + if( PHB_CURLM_is( 1 ) && HB_ISBYREF( 2 ) ) + { + + CURLMcode res = ( CURLMcode ) HB_CURLM_INTERNAL_ERROR; + PHB_CURLM hb_curlm = PHB_CURLM_par( 1 ); + + if ( hb_curlm ) + { + int running_handles = 0; + res = curl_multi_perform( hb_curlm->curlm, &running_handles); + hb_stornl( running_handles, 2); + } + + hb_retnl( ( long ) res ); + + } + else + hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); +} + +HB_FUNC( CURL_MULTI_POLL ) +{ + if( PHB_CURLM_is( 1 ) && HB_ISNUM( 2 ) ) + { + + CURLMcode res = ( CURLMcode ) HB_CURLM_INTERNAL_ERROR; + PHB_CURLM hb_curlm = PHB_CURLM_par( 1 ); + + if ( hb_curlm ) + { + res = curl_multi_poll( hb_curlm->curlm, + NULL, + 0, + hb_parni(2), + NULL ); + } + + hb_retnl( ( long ) res ); + + } + else + hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); +} + + +HB_FUNC( CURL_MULTI_INFO_READ ) +{ + if( PHB_CURLM_is( 1 ) ) + { + + PHB_ITEM pReturn = NULL; + PHB_CURLM hb_curlm = PHB_CURLM_par( 1 ); + + if ( hb_curlm ) + { + int msgs_in_queue = 0; + + struct CURLMsg *msg = curl_multi_info_read( hb_curlm->curlm, &msgs_in_queue ); + if ( msg ) + { + + CURLcode res = ( CURLcode ) HB_CURLE_ERROR; + long response_code = 0; + res = curl_easy_getinfo( msg->easy_handle, CURLINFO_RESPONSE_CODE, &response_code ); + + pReturn = hb_itemArrayNew( HB_CURLMSG_RESP_LAST ); + + hb_arraySetNL( pReturn, HB_CURLMSG_RESP_LEN, ( long ) msgs_in_queue ); + hb_arraySetNL( pReturn, HB_CURLMSG_RESP_RESPONSE_CODE, ( long ) response_code ); + hb_arraySetNL( pReturn, HB_CURLMSG_RESP_MSG, ( long ) msg->msg ); + hb_arraySetNL( pReturn, HB_CURLMSG_RESP_RESULT, ( long ) msg->data.result ); + + } + } + + if ( pReturn ) + hb_itemReturnRelease( pReturn ); + else + hb_ret(); + + } + else + hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + +} + /* Harbour interface (session independent) */ /* NOTE: Obsolete, superceded by curl_easy_escape() */ diff --git a/contrib/hbcurl/hbcurl.ch b/contrib/hbcurl/hbcurl.ch index 193165af34..b1b4177934 100644 --- a/contrib/hbcurl/hbcurl.ch +++ b/contrib/hbcurl/hbcurl.ch @@ -578,4 +578,32 @@ #define HB_CURLE_FTP_BAD_FILE_LIST 87 /* unable to parse FTP file list */ #define HB_CURLE_CHUNK_FAILED 88 /* chunk callback reported error */ +/* curl multi result codes. */ + +#define HB_CURLM_CALL_MULTI_PERFORM -1 /* please call curl_multi_perform() or curl_multi_socket*() soon */ +#define HB_CURLM_OK 0 +#define HB_CURLM_BAD_HANDLE 1 /* the passed-in handle is not a valid CURLM handle */ +#define HB_CURLM_BAD_EASY_HANDLE 2 /* an easy handle was not good/valid */ +#define HB_CURLM_OUT_OF_MEMORY 3 /* if you ever get this, you're in deep sh*t */ +#define HB_CURLM_INTERNAL_ERROR 4 /* this is a libcurl bug */ +#define HB_CURLM_BAD_SOCKET 5 /* the passed in socket argument did not match */ +#define HB_CURLM_UNKNOWN_OPTION 6 /* curl_multi_setopt() with unsupported option */ +#define HB_CURLM_ADDED_ALREADY 7 /* an easy handle already added to a multi handle was attempted to get added - again */ +#define HB_CURLM_RECURSIVE_API_CALL 8 /* an api function was called from inside a callback */ +#define HB_CURLM_WAKEUP_FAILURE 9 /* wakeup is unavailable or failed */ +#define HB_CURLM_BAD_FUNCTION_ARGUMENT 10 /* function called with a bad parameter */ +#define HB_CURLM_ABORTED_BY_CALLBACK 11 +#define HB_CURLM_UNRECOVERABLE_POLL 12 + +/* curl_multi_info_read result codes. */ + +#define HB_CURLMSG_NONE 0 /* first, not used */ +#define HB_CURLMSG_DONE 1 /* This easy handle has completed. 'result' contains the CURLcode of the transfer */ + +#define HB_CURLMSG_RESP_LEN 1 /* queue len */ +#define HB_CURLMSG_RESP_RESPONSE_CODE 2 /* curl_easy_getinfo( msg->easy_handle, CURLINFO_RESPONSE_CODE ) */ +#define HB_CURLMSG_RESP_MSG 3 /* CURLMSG */ +#define HB_CURLMSG_RESP_RESULT 4 /* CURLcode */ +#define HB_CURLMSG_RESP_LAST HB_CURLMSG_RESP_RESULT + #endif /* HBCURL_CH_ */