mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Implement curl server push
This commit is contained in:
parent
d56d2f452b
commit
ad15e1ccda
3 changed files with 124 additions and 5 deletions
|
@ -1337,6 +1337,9 @@ PHP_MINIT_FUNCTION(curl)
|
|||
|
||||
#if LIBCURL_VERSION_NUM >= 0x072e00 /* Available since 7.46.0 */
|
||||
REGISTER_CURL_CONSTANT(CURLOPT_STREAM_WEIGHT);
|
||||
REGISTER_CURL_CONSTANT(CURLMOPT_PUSHFUNCTION);
|
||||
REGISTER_CURL_CONSTANT(CURL_PUSH_OK);
|
||||
REGISTER_CURL_CONSTANT(CURL_PUSH_DENY);
|
||||
#endif
|
||||
|
||||
#if LIBCURL_VERSION_NUM >= 0x072f00 /* Available since 7.47.0 */
|
||||
|
@ -1853,7 +1856,7 @@ PHP_FUNCTION(curl_version)
|
|||
|
||||
/* {{{ alloc_curl_handle
|
||||
*/
|
||||
static php_curl *alloc_curl_handle()
|
||||
php_curl *alloc_curl_handle()
|
||||
{
|
||||
php_curl *ch = ecalloc(1, sizeof(php_curl));
|
||||
ch->to_free = ecalloc(1, sizeof(struct _php_curl_free));
|
||||
|
@ -3399,10 +3402,12 @@ static void _php_curl_close_ex(php_curl *ch)
|
|||
*
|
||||
* Libcurl commit d021f2e8a00 fix this issue and should be part of 7.28.2
|
||||
*/
|
||||
curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing);
|
||||
curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing);
|
||||
if (ch->cp != NULL) {
|
||||
curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing);
|
||||
curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing);
|
||||
|
||||
curl_easy_cleanup(ch->cp);
|
||||
curl_easy_cleanup(ch->cp);
|
||||
}
|
||||
|
||||
/* cURL destructors should be invoked only by last curl handle */
|
||||
if (--(*ch->clone) == 0) {
|
||||
|
|
106
ext/curl/multi.c
106
ext/curl/multi.c
|
@ -63,6 +63,7 @@ PHP_FUNCTION(curl_multi_init)
|
|||
|
||||
mh = ecalloc(1, sizeof(php_curlm));
|
||||
mh->multi = curl_multi_init();
|
||||
mh->handlers = ecalloc(1, sizeof(php_curlm_handlers));
|
||||
|
||||
zend_llist_init(&mh->easyh, sizeof(zval), _php_curl_multi_cleanup_list, 0);
|
||||
|
||||
|
@ -400,6 +401,12 @@ void _php_curl_multi_close(zend_resource *rsrc) /* {{{ */
|
|||
|
||||
curl_multi_cleanup(mh->multi);
|
||||
zend_llist_clean(&mh->easyh);
|
||||
if (mh->handlers->server_push) {
|
||||
efree(mh->handlers->server_push);
|
||||
}
|
||||
if (mh->handlers) {
|
||||
efree(mh->handlers);
|
||||
}
|
||||
efree(mh);
|
||||
rsrc->ptr = NULL;
|
||||
}
|
||||
|
@ -447,6 +454,83 @@ PHP_FUNCTION(curl_multi_strerror)
|
|||
/* }}} */
|
||||
#endif
|
||||
|
||||
#if LIBCURL_VERSION_NUM >= 0x072C00 /* Available since 7.44.0 */
|
||||
|
||||
static int _php_server_push_callback(CURL *parent_ch, CURL *easy, size_t num_headers, struct curl_pushheaders *push_headers, void *userp) /* {{{ */
|
||||
{
|
||||
php_curl *ch;
|
||||
php_curl *parent;
|
||||
php_curlm *mh = (php_curlm *)userp;
|
||||
size_t rval = CURL_PUSH_DENY;
|
||||
php_curlm_server_push *t = mh->handlers->server_push;
|
||||
zval *pz_parent_ch = NULL;
|
||||
zval pz_ch;
|
||||
zval headers;
|
||||
zval retval;
|
||||
zend_resource *res;
|
||||
char *header;
|
||||
int error;
|
||||
zend_fcall_info fci = empty_fcall_info;
|
||||
|
||||
pz_parent_ch = _php_curl_multi_find_easy_handle(mh, parent_ch);
|
||||
if (pz_parent_ch == NULL) {
|
||||
return rval;
|
||||
}
|
||||
|
||||
parent = (php_curl*)zend_fetch_resource(Z_RES_P(pz_parent_ch), le_curl_name, le_curl);
|
||||
|
||||
ch = alloc_curl_handle();
|
||||
ch->cp = easy;
|
||||
_php_setup_easy_copy_handlers(ch, parent);
|
||||
|
||||
Z_ADDREF_P(pz_parent_ch);
|
||||
|
||||
res = zend_register_resource(ch, le_curl);
|
||||
ZVAL_RES(&pz_ch, res);
|
||||
|
||||
size_t i;
|
||||
array_init(&headers);
|
||||
for(i=0; i<num_headers; i++) {
|
||||
header = curl_pushheader_bynum(push_headers, i);
|
||||
add_next_index_string(&headers, header);
|
||||
}
|
||||
|
||||
zend_fcall_info_init(&t->func_name, 0, &fci, &t->fci_cache, NULL, NULL);
|
||||
|
||||
zend_fcall_info_argn(
|
||||
&fci, 3,
|
||||
pz_parent_ch,
|
||||
&pz_ch,
|
||||
&headers
|
||||
);
|
||||
|
||||
fci.retval = &retval;
|
||||
|
||||
error = zend_call_function(&fci, &t->fci_cache);
|
||||
zend_fcall_info_args_clear(&fci, 1);
|
||||
zval_dtor(&headers);
|
||||
|
||||
if (error == FAILURE) {
|
||||
php_error_docref(NULL, E_WARNING, "Cannot call the CURLMOPT_PUSHFUNCTION");
|
||||
} else if (!Z_ISUNDEF(retval)) {
|
||||
if (CURL_PUSH_DENY != zval_get_long(&retval)) {
|
||||
rval = CURL_PUSH_OK;
|
||||
|
||||
/* we want to create a copy of this zval that we store in the multihandle structure element "easyh" */
|
||||
zval tmp_val;
|
||||
ZVAL_DUP(&tmp_val, &pz_ch);
|
||||
zend_llist_add_element(&mh->easyh, &tmp_val);
|
||||
} else {
|
||||
/* libcurl will free this easy handle, avoid double free */
|
||||
ch->cp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */
|
||||
static int _php_curl_multi_setopt(php_curlm *mh, zend_long option, zval *zvalue, zval *return_value) /* {{{ */
|
||||
{
|
||||
|
@ -468,7 +552,29 @@ static int _php_curl_multi_setopt(php_curlm *mh, zend_long option, zval *zvalue,
|
|||
#endif
|
||||
error = curl_multi_setopt(mh->multi, option, zval_get_long(zvalue));
|
||||
break;
|
||||
#if LIBCURL_VERSION_NUM > 0x072D00 /* Available since 7.46.0 */
|
||||
case CURLMOPT_PUSHFUNCTION:
|
||||
if (mh->handlers->server_push == NULL) {
|
||||
mh->handlers->server_push = ecalloc(1, sizeof(php_curlm_server_push));
|
||||
} else if (!Z_ISUNDEF(mh->handlers->server_push->func_name)) {
|
||||
zval_ptr_dtor(&mh->handlers->server_push->func_name);
|
||||
mh->handlers->server_push->fci_cache = empty_fcall_info_cache;
|
||||
}
|
||||
|
||||
ZVAL_COPY(&mh->handlers->server_push->func_name, zvalue);
|
||||
mh->handlers->server_push->method = PHP_CURL_USER;
|
||||
if (!Z_ISUNDEF(mh->handlers->server_push->func_name)) {
|
||||
zval_ptr_dtor(&mh->handlers->server_push->func_name);
|
||||
mh->handlers->server_push->fci_cache = empty_fcall_info_cache;
|
||||
|
||||
}
|
||||
error = curl_multi_setopt(mh->multi, option, _php_server_push_callback);
|
||||
if (error != CURLM_OK) {
|
||||
return 0;
|
||||
}
|
||||
error = curl_multi_setopt(mh->multi, CURLMOPT_PUSHDATA, mh);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
php_error_docref(NULL, E_WARNING, "Invalid curl multi configuration option");
|
||||
error = CURLM_UNKNOWN_OPTION;
|
||||
|
|
|
@ -66,6 +66,8 @@ extern int le_curl_multi_handle;
|
|||
#define le_curl_multi_handle_name "cURL Multi Handle"
|
||||
extern int le_curl_share_handle;
|
||||
#define le_curl_share_handle_name "cURL Share Handle"
|
||||
//extern int le_curl_pushheaders;
|
||||
//#define le_curl_pushheaders "cURL Push Headers"
|
||||
|
||||
PHP_MINIT_FUNCTION(curl);
|
||||
PHP_MSHUTDOWN_FUNCTION(curl);
|
||||
|
@ -146,7 +148,7 @@ typedef struct {
|
|||
zval func_name;
|
||||
zend_fcall_info_cache fci_cache;
|
||||
int method;
|
||||
} php_curl_progress, php_curl_fnmatch;
|
||||
} php_curl_progress, php_curl_fnmatch, php_curlm_server_push;
|
||||
|
||||
typedef struct {
|
||||
php_curl_write *write;
|
||||
|
@ -190,10 +192,15 @@ typedef struct {
|
|||
|
||||
#define CURLOPT_SAFE_UPLOAD -1
|
||||
|
||||
typedef struct {
|
||||
php_curlm_server_push *server_push;
|
||||
} php_curlm_handlers;
|
||||
|
||||
typedef struct {
|
||||
int still_running;
|
||||
CURLM *multi;
|
||||
zend_llist easyh;
|
||||
php_curlm_handlers *handlers;
|
||||
struct {
|
||||
int no;
|
||||
} err;
|
||||
|
@ -206,6 +213,7 @@ typedef struct {
|
|||
} err;
|
||||
} php_curlsh;
|
||||
|
||||
php_curl *alloc_curl_handle();
|
||||
void _php_curl_cleanup_handle(php_curl *);
|
||||
void _php_curl_multi_cleanup_list(void *data);
|
||||
void _php_curl_verify_handlers(php_curl *ch, int reporterror);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue