Skip to content

Commit

Permalink
Refactor curl native hook, Fix curl tests
Browse files Browse the repository at this point in the history
  • Loading branch information
matyhtf committed Oct 23, 2024
1 parent 8b89482 commit 496498d
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 164 deletions.
4 changes: 3 additions & 1 deletion ext-src/php_swoole_curl.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ SW_EXTERN_C_END
#error "require cURL version 7.56.0 or later"
#endif

namespace swoole {
CURLcode swoole_curl_easy_perform(CURL *cp);
php_curl *swoole_curl_get_handle(zval *zid, bool exclusive = true, bool required = true);

namespace swoole {
namespace curl {

class Multi;
Expand Down
24 changes: 23 additions & 1 deletion ext-src/swoole_curl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
namespace swoole {
namespace curl {

static std::unordered_map<CURL *, Handle *> handle_buckets;
static SW_THREAD_LOCAL std::unordered_map<CURL *, Handle *> handle_buckets;

Handle *get_handle(CURL *cp) {
auto iter = handle_buckets.find(cp);
Expand Down Expand Up @@ -488,4 +488,26 @@ void Multi::callback(Handle *handle, int event_bitmask, int sockfd) {
}
} // namespace curl
} // namespace swoole

CURLcode swoole_curl_easy_perform(CURL *cp) {
Multi *multi = new Multi();
CURLcode error = multi->exec(swoole::curl::get_handle(cp));
delete multi;
return error;
}

php_curl *swoole_curl_get_handle(zval *zid, bool exclusive, bool required) {
php_curl *ch = Z_CURL_P(zid);
if (SWOOLE_G(req_status) == PHP_SWOOLE_RSHUTDOWN_END) {
exclusive = false;
}
if (exclusive && swoole_coroutine_is_in()) {
auto handle = swoole::curl::get_handle(ch->cp);
if (handle && handle->multi && handle->multi->check_bound_co() == nullptr) {
return nullptr;
}
}
return ch;
}

#endif
7 changes: 6 additions & 1 deletion tests/swoole_curl/fatal_error_in_callback.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ run(function () {
});

register_shutdown_function(function () use ($ch) {
curl_close($ch);
try {
curl_close($ch);
} catch (throwable $e) {
trigger_error($e->getMessage(), E_USER_WARNING);
}

});

curl_exec($ch);
Expand Down
6 changes: 5 additions & 1 deletion tests/swoole_curl/upload/1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ $cm->run(function ($host) {
curl_setopt($ch, CURLOPT_POSTFIELDS, array("file" => $file));
var_dump(curl_exec($ch));

curl_setopt($ch, CURLOPT_SAFE_UPLOAD, 0);
try {
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, 0);
} catch (throwable $e) {
trigger_error($e->getMessage(), E_USER_WARNING);
}
$params = array('file' => '@' . __DIR__ . '/curl_testdata1.txt');
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
var_dump(curl_exec($ch));
Expand Down
15 changes: 0 additions & 15 deletions thirdparty/php/curl/curl_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,20 +111,14 @@ struct _php_curl_free {

typedef struct {
CURL *cp;
#if PHP_VERSION_ID >= 80100
php_curl_handlers handlers;
#else
php_curl_handlers *handlers;
#endif
struct _php_curl_free *to_free;
struct _php_curl_send_headers header;
struct _php_curl_error err;
zend_bool in_callback;
uint32_t *clone;
zval postfields;
#if PHP_VERSION_ID >= 80100
zval private_data;
#endif
/* CurlShareHandle object set using CURLOPT_SHARE. */
struct _php_curlsh *share;
zend_object std;
Expand All @@ -145,16 +139,9 @@ class Multi;
using swoole::curl::Multi;

typedef struct {
#if PHP_VERSION_ID < 80100
int still_running;
#endif
Multi *multi;
zend_llist easyh;
#if PHP_VERSION_ID >= 80100
php_curlm_handlers handlers;
#else
php_curlm_handlers *handlers;
#endif
struct {
int no;
} err;
Expand Down Expand Up @@ -206,7 +193,5 @@ static inline php_curlsh *curl_share_from_obj(zend_object *obj) {
void curl_multi_register_class(const zend_function_entry *method_entries);
curl_result_t swoole_curl_cast_object(zend_object *obj, zval *result, int type);

php_curl *swoole_curl_get_handle(zval *zid, bool exclusive = true, bool required = true);

#endif /* _PHP_CURL_PRIVATE_H */
#endif
75 changes: 17 additions & 58 deletions thirdparty/php/curl/interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,43 +111,6 @@ static zend_object_handlers swoole_native_curl_exception_handlers;
return;
#endif

void swoole_curl_set_private_data(php_curl *ch, zval *zvalue) {
#if PHP_VERSION_ID >= 80100
zval_ptr_dtor(&ch->private_data);
ZVAL_COPY(&ch->private_data, zvalue);
#else
zend_update_property_ex(nullptr, &ch->std, SW_ZSTR_KNOWN(SW_ZEND_STR_PRIVATE_DATA), zvalue);
#endif
}

void swoole_curl_get_private_data(php_curl *ch, zval *return_value) {
#if PHP_VERSION_ID >= 80100
if (!Z_ISUNDEF(ch->private_data)) {
RETURN_COPY(&ch->private_data);
} else {
RETURN_FALSE;
}
#else
zval rv;
zval *zv = zend_read_property_ex(nullptr, &ch->std, SW_ZSTR_KNOWN(SW_ZEND_STR_PRIVATE_DATA), 1, &rv);
RETURN_COPY(zv);
#endif
}

php_curl *swoole_curl_get_handle(zval *zid, bool exclusive, bool required) {
php_curl *ch = Z_CURL_P(zid);
if (SWOOLE_G(req_status) == PHP_SWOOLE_RSHUTDOWN_END) {
exclusive = false;
}
if (exclusive && swoole_coroutine_is_in()) {
auto handle = swoole::curl::get_handle(ch->cp);
if (handle && handle->multi && handle->multi->check_bound_co() == nullptr) {
return nullptr;
}
}
return ch;
}

static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, const size_t len) {
if (strlen(str) != len) {
zend_value_error("%s(): cURL option must not contain any null bytes", get_active_function_name());
Expand Down Expand Up @@ -304,15 +267,16 @@ static zend_function *swoole_curl_get_constructor(zend_object *object) {
}

static zend_object *swoole_curl_clone_obj(zend_object *object) {
zend_object *clone_object = swoole_curl_create_object(curl_ce);
php_curl *clone_ch = curl_from_obj(clone_object);

php_curl *ch = curl_from_obj(object);
CURL *cp = curl_easy_duphandle(ch->cp);
if (!cp) {
zend_throw_exception(NULL, "Failed to clone CurlHandle", 0);
return nullptr;
return &clone_ch->std;
}

zend_object *clone_object = swoole_curl_create_object(curl_ce);
php_curl *clone_ch = curl_from_obj(clone_object);
swoole_curl_init_handle(clone_ch);

clone_ch->cp = cp;
Expand Down Expand Up @@ -1094,9 +1058,7 @@ void swoole_setup_easy_copy_handlers(php_curl *ch, php_curl *source) {
}
#endif

#if PHP_VERSION_ID >= 80100
ZVAL_COPY(&ch->private_data, &source->private_data);
#endif

efree(ch->to_free->slist);
efree(ch->to_free);
Expand Down Expand Up @@ -1195,7 +1157,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
size_t filesize = -1;
curl_seek_callback seekfunc = seek_cb;

prop = zend_read_property(curl_CURLFile_class, SW_Z8_OBJ_P(current), "name", sizeof("name") - 1, 0, &rv);
prop = zend_read_property(curl_CURLFile_class, Z_OBJ_P(current), "name", sizeof("name") - 1, 0, &rv);
if (Z_TYPE_P(prop) != IS_STRING) {
php_error_docref(NULL, E_WARNING, "Invalid filename for key %s", ZSTR_VAL(string_key));
} else {
Expand All @@ -1206,12 +1168,12 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
}

prop =
zend_read_property(curl_CURLFile_class, SW_Z8_OBJ_P(current), "mime", sizeof("mime") - 1, 0, &rv);
zend_read_property(curl_CURLFile_class, Z_OBJ_P(current), "mime", sizeof("mime") - 1, 0, &rv);
if (Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) {
type = Z_STRVAL_P(prop);
}
prop = zend_read_property(
curl_CURLFile_class, SW_Z8_OBJ_P(current), "postname", sizeof("postname") - 1, 0, &rv);
curl_CURLFile_class, Z_OBJ_P(current), "postname", sizeof("postname") - 1, 0, &rv);
if (Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) {
filename = Z_STRVAL_P(prop);
}
Expand Down Expand Up @@ -1296,12 +1258,7 @@ PHP_FUNCTION(swoole_native_curl_copy_handle) {
RETURN_FALSE;
}

zend_object *clone_obj = swoole_curl_clone_obj(Z_OBJ_P(zid));
if (!clone_obj) {
php_error_docref(NULL, E_WARNING, "Cannot duplicate cURL handle");
RETURN_FALSE;
}
RETURN_OBJ(clone_obj);
RETURN_OBJ(swoole_curl_clone_obj(Z_OBJ_P(zid)));
}
/* }}} */

Expand Down Expand Up @@ -1560,7 +1517,8 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i

/* Curl private option */
case CURLOPT_PRIVATE: {
swoole_curl_set_private_data(ch, zvalue);
zval_ptr_dtor(&ch->private_data);
ZVAL_COPY(&ch->private_data, zvalue);
return SUCCESS;
}

Expand Down Expand Up @@ -2053,10 +2011,7 @@ PHP_FUNCTION(swoole_native_curl_exec) {

swoole_curl_verify_handlers(ch, 1);
swoole_curl_cleanup_handle(ch);

Multi *multi = new Multi();
error = multi->exec(swoole::curl::get_handle(ch->cp));
delete multi;
error = swoole_curl_easy_perform(ch->cp);
SAVE_CURL_ERROR(ch, error);

if (error != CURLE_OK) {
Expand Down Expand Up @@ -2286,8 +2241,12 @@ PHP_FUNCTION(swoole_native_curl_getinfo) {
break;
}
case CURLINFO_PRIVATE: {
swoole_curl_get_private_data(ch, return_value);
return;
if (!Z_ISUNDEF(ch->private_data)) {
RETURN_COPY(&ch->private_data);
} else {
RETURN_FALSE;
}
break;
}
default: {
int type = CURLINFO_TYPEMASK & option;
Expand Down
13 changes: 0 additions & 13 deletions thirdparty/php/curl/multi.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,6 @@ PHP_FUNCTION(swoole_native_curl_multi_init) {
mh = Z_CURL_MULTI_P(return_value);
mh->multi = new Multi();
mh->multi->set_selector(new Selector());
#if PHP_VERSION_ID < 80100
mh->handlers = (php_curlm_handlers *) ecalloc(1, sizeof(php_curlm_handlers));
#endif
swoole_curl_multi_set_in_coroutine(mh, true);
zend_llist_init(&mh->easyh, sizeof(zval), swoole_curl_multi_cleanup_list, 0);
}
Expand Down Expand Up @@ -643,20 +640,10 @@ static void _php_curl_multi_free(php_curlm *mh) {
mh->multi = nullptr;
}
zend_llist_clean(&mh->easyh);
#if PHP_VERSION_ID < 80100
if (mh->handlers->server_push) {
zval_ptr_dtor(&mh->handlers->server_push->func_name);
efree(mh->handlers->server_push);
}
if (mh->handlers) {
efree(mh->handlers);
}
#else
if (mh->handlers.server_push) {
zval_ptr_dtor(&mh->handlers.server_push->func_name);
efree(mh->handlers.server_push);
}
#endif
}

#endif
Loading

0 comments on commit 496498d

Please sign in to comment.