From 7dc5de0b79846bfe33ca36a9eeb894ef2ecfdee1 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Sat, 21 May 2011 15:46:12 +0000 Subject: [PATCH] * use the resource factory * use the separator where applicable --- config9.m4 | 2 + php_http_curl.c | 292 +++++++++++++++++++++++------------ php_http_curl.h | 7 + php_http_encoding.c | 4 +- php_http_neon.c | 148 +++++++++--------- php_http_neon.h | 7 + php_http_persistent_handle.c | 160 +++++++++++++------ php_http_persistent_handle.h | 34 +++- php_http_request.c | 51 +++--- php_http_request.h | 86 +++++++---- php_http_request_datashare.c | 15 +- php_http_request_datashare.h | 5 +- php_http_request_factory.c | 255 ++++++++++++++++++------------ php_http_request_pool.c | 23 +-- php_http_request_pool.h | 7 +- 15 files changed, 705 insertions(+), 391 deletions(-) diff --git a/config9.m4 b/config9.m4 index c59c53f..c4486df 100644 --- a/config9.m4 +++ b/config9.m4 @@ -444,6 +444,7 @@ dnl ---- php_http_negotiate.c \ php_http_object.c \ php_http_params.c \ + php_http_resource_factory.c \ php_http_persistent_handle.c \ php_http_property_proxy.c \ php_http_querystring.c \ @@ -486,6 +487,7 @@ dnl ---- php_http_negotiate.h \ php_http_object.h \ php_http_params.h \ + php_http_resource_factory.h \ php_http_persistent_handle.h \ php_http_property_proxy.h \ php_http_querystring.h \ diff --git a/php_http_curl.c b/php_http_curl.c index 307d488..71365dc 100644 --- a/php_http_curl.c +++ b/php_http_curl.c @@ -76,7 +76,7 @@ typedef struct php_http_curl_request_datashare { } #define PHP_HTTP_CURL_OPT_STRING_EX(keyname, optname, obdc) \ if (!strcasecmp(key.str, keyname)) { \ - zval *copy = cache_option(&curl->options.cache, keyname, strlen(keyname)+1, 0, php_http_zsep(IS_STRING, *param)); \ + zval *copy = cache_option(&curl->options.cache, keyname, strlen(keyname)+1, 0, php_http_ztyp(IS_STRING, *param)); \ if (obdc) { \ if (SUCCESS != php_check_open_basedir(Z_STRVAL_P(copy) TSRMLS_CC)) { \ return FAILURE; \ @@ -93,7 +93,7 @@ typedef struct php_http_curl_request_datashare { } #define PHP_HTTP_CURL_OPT_LONG_EX(keyname, optname) \ if (!strcasecmp(key.str, keyname)) { \ - zval *copy = php_http_zsep(IS_LONG, *param); \ + zval *copy = php_http_ztyp(IS_LONG, *param); \ curl_easy_setopt(ch, optname, Z_LVAL_P(copy)); \ zval_ptr_dtor(©); \ continue; \ @@ -113,6 +113,69 @@ static inline php_http_curl_request_storage_t *get_storage(CURL *ch) { return st; } +/* resource_factory ops */ + +static void *php_http_curl_ctor(void *opaque TSRMLS_DC) +{ + void *ch; + + if ((ch = curl_easy_init())) { + get_storage(ch); + return ch; + } + return NULL; +} + +static void *php_http_curl_copy(void *opaque, void *handle TSRMLS_DC) +{ + void *ch; + + if ((ch = curl_easy_duphandle(handle))) { + get_storage(ch); + return ch; + } + return NULL; +} + +static void php_http_curl_dtor(void *opaque, void *handle TSRMLS_DC) +{ + php_http_curl_request_storage_t *st = get_storage(handle); + + curl_easy_cleanup(handle); + + if (st) { + if (st->url) { + pefree(st->url, 1); + } + if (st->cookiestore) { + pefree(st->cookiestore, 1); + } + pefree(st, 1); + } +} + +static void *php_http_curlm_ctor(void *opaque TSRMLS_DC) +{ + return curl_multi_init(); +} + +static void php_http_curlm_dtor(void *opaque, void *handle TSRMLS_DC) +{ + curl_multi_cleanup(handle); +} + +static void *php_http_curlsh_ctor(void *opaque TSRMLS_DC) +{ + return curl_share_init(); +} + +static void php_http_curlsh_dtor(void *opaque, void *handle TSRMLS_DC) +{ + curl_share_cleanup(handle); +} + +/* callbacks */ + static size_t php_http_curl_read_callback(void *data, size_t len, size_t n, void *ctx) { php_http_message_body_t *body = ctx; @@ -165,6 +228,35 @@ static int php_http_curl_raw_callback(CURL *ch, curl_infotype type, char *data, php_http_curl_request_t *curl = h->ctx; unsigned flags = 0; + /* catch progress */ + switch (type) { + case CURLINFO_TEXT: + if (php_memnstr(data, ZEND_STRL("About to connect"), data + length)) { + curl->progress.state.info = "resolve"; + } else if (php_memnstr(data, ZEND_STRL("Trying"), data + length)) { + curl->progress.state.info = "connect"; + } else if (php_memnstr(data, ZEND_STRL("Connected"), data + length)) { + curl->progress.state.info = "connected"; + } else if (php_memnstr(data, ZEND_STRL("left intact"), data + length)) { + curl->progress.state.info = "not disconnected"; + } else if (php_memnstr(data, ZEND_STRL("closed"), data + length)) { + curl->progress.state.info = "disconnected"; + } + php_http_request_progress_notify(&curl->progress TSRMLS_CC); + break; + case CURLINFO_HEADER_OUT: + case CURLINFO_DATA_OUT: + case CURLINFO_SSL_DATA_OUT: + curl->progress.state.info = "send"; + break; + case CURLINFO_HEADER_IN: + case CURLINFO_DATA_IN: + case CURLINFO_SSL_DATA_IN: + curl->progress.state.info = "receive"; + break; + default: + break; + } /* process data */ switch (type) { case CURLINFO_HEADER_IN: @@ -478,7 +570,7 @@ static inline zval *get_option(HashTable *cache, HashTable *options, char *key, ulong h = zend_hash_func(key, keylen); if (SUCCESS == zend_hash_quick_find(options, key, keylen, h, (void *) &zoption)) { - zval *option = php_http_zsep(type, *zoption); + zval *option = php_http_ztyp(type, *zoption); if (cache) { zval *cached = cache_option(cache, key, keylen, h, option); @@ -575,8 +667,8 @@ static STATUS set_options(php_http_request_t *h, HashTable *options) if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &prs)) { zend_hash_move_forward(Z_ARRVAL_P(zoption)); if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &pre)) { - zval *prs_cpy = php_http_zsep(IS_LONG, *prs); - zval *pre_cpy = php_http_zsep(IS_LONG, *pre); + zval *prs_cpy = php_http_ztyp(IS_LONG, *prs); + zval *pre_cpy = php_http_ztyp(IS_LONG, *pre); if (Z_LVAL_P(prs_cpy) && Z_LVAL_P(pre_cpy)) { curl_easy_setopt(ch, CURLOPT_LOCALPORT, MIN(Z_LVAL_P(prs_cpy), Z_LVAL_P(pre_cpy))); @@ -674,8 +766,8 @@ static STATUS set_options(php_http_request_t *h, HashTable *options) if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr), (void *) &re, &pos2)) { if ( ((Z_TYPE_PP(rb) == IS_LONG) || ((Z_TYPE_PP(rb) == IS_STRING) && is_numeric_string(Z_STRVAL_PP(rb), Z_STRLEN_PP(rb), NULL, NULL, 1))) && ((Z_TYPE_PP(re) == IS_LONG) || ((Z_TYPE_PP(re) == IS_STRING) && is_numeric_string(Z_STRVAL_PP(re), Z_STRLEN_PP(re), NULL, NULL, 1)))) { - zval *rbl = php_http_zsep(IS_LONG, *rb); - zval *rel = php_http_zsep(IS_LONG, *re); + zval *rbl = php_http_ztyp(IS_LONG, *rb); + zval *rel = php_http_ztyp(IS_LONG, *re); if ((Z_LVAL_P(rbl) >= 0) && (Z_LVAL_P(rel) >= 0)) { php_http_buffer_appendf(&rs, "%ld-%ld,", Z_LVAL_P(rbl), Z_LVAL_P(rel)); @@ -715,7 +807,7 @@ static STATUS set_options(php_http_request_t *h, HashTable *options) php_http_buffer_init(&header); FOREACH_KEYVAL(pos, zoption, header_key, header_val) { if (header_key.type == HASH_KEY_IS_STRING) { - zval *header_cpy = php_http_zsep(IS_STRING, *header_val); + zval *header_cpy = php_http_ztyp(IS_STRING, *header_val); if (!strcasecmp(header_key.str, "range")) { range_req = 1; @@ -780,7 +872,7 @@ static STATUS set_options(php_http_request_t *h, HashTable *options) FOREACH_KEYVAL(pos, zoption, cookie_key, cookie_val) { if (cookie_key.type == HASH_KEY_IS_STRING) { - zval *val = php_http_zsep(IS_STRING, *cookie_val); + zval *val = php_http_ztyp(IS_STRING, *cookie_val); php_http_buffer_appendf(&curl->options.cookies, "%s=%s; ", cookie_key.str, Z_STRVAL_P(val)); zval_ptr_dtor(&val); } @@ -1099,7 +1191,8 @@ static php_http_request_datashare_t *php_http_curl_request_datashare_init(php_ht { php_http_curl_request_datashare_t *curl; - if (!handle && (SUCCESS != php_http_persistent_handle_acquire(ZEND_STRL("http_request_datashare.curl"), &handle TSRMLS_CC))) { + if (!handle && !(handle = php_http_resource_factory_handle_ctor(h->rf TSRMLS_CC))) { + php_http_error(HE_WARNING, PHP_HTTP_E_REQUEST_DATASHARE, "could not initialize curl share handle"); return NULL; } @@ -1107,7 +1200,8 @@ static php_http_request_datashare_t *php_http_curl_request_datashare_init(php_ht curl->handle = handle; #ifdef ZTS if (h->persistent) { - if (SUCCESS == php_http_persistent_handle_acquire(ZEND_STRL("http_request_datashare_lock.curl"), (void *) &curl->locks)) { + curl->locks = php_http_request_datashare_locks_init(); + if (curl->locks) { curl_share_setopt(share->ch, CURLSHOPT_LOCKFUNC, php_http_curl_request_datashare_lock_func); curl_share_setopt(share->ch, CURLSHOPT_UNLOCKFUNC, php_http_curl_request_datashare_unlock_func); curl_share_setopt(share->ch, CURLSHOPT_USERDATA, curl->locks); @@ -1124,14 +1218,16 @@ static void php_http_curl_request_datashare_dtor(php_http_request_datashare_t *h php_http_curl_request_datashare_t *curl = h->ctx; TSRMLS_FETCH_FROM_CTX(h->ts); - php_http_persistent_handle_release(ZEND_STRL("http_request_datashare.curl"), &curl->handle TSRMLS_CC); + php_http_resource_factory_handle_dtor(h->rf, curl->handle TSRMLS_CC); #ifdef ZTS if (h->persistent) { - php_http_persistent_handle_release(ZEND_STRL("http_request_datashare_lock.curl"), (void *) &curl->locks TSRMLS_CC); + http_request_datashare_locks_dtor(curl->locks); } #endif + pefree(curl, h->persistent); + h->ctx = NULL; } static STATUS php_http_curl_request_datashare_attach(php_http_request_datashare_t *h, php_http_request_t *r) @@ -1193,7 +1289,14 @@ static STATUS php_http_curl_request_datashare_setopt(php_http_request_datashare_ return SUCCESS; } +static php_http_resource_factory_ops_t php_http_curlsh_resource_factory_ops = { + php_http_curlsh_ctor, + NULL, + php_http_curlsh_dtor +}; + static php_http_request_datashare_ops_t php_http_curl_request_datashare_ops = { + &php_http_curlsh_resource_factory_ops, php_http_curl_request_datashare_init, NULL /* copy */, php_http_curl_request_datashare_dtor, @@ -1215,7 +1318,8 @@ static php_http_request_pool_t *php_http_curl_request_pool_init(php_http_request { php_http_curl_request_pool_t *curl; - if (!handle && (SUCCESS != php_http_persistent_handle_acquire(ZEND_STRL("http_request_pool.curl"), &handle TSRMLS_CC))) { + if (!handle && !(handle = php_http_resource_factory_handle_ctor(h->rf TSRMLS_CC))) { + php_http_error(HE_WARNING, PHP_HTTP_E_REQUEST_POOL, "could not initialize curl pool handle"); return NULL; } @@ -1240,7 +1344,8 @@ static void php_http_curl_request_pool_dtor(php_http_request_pool_t *h) #endif curl->unfinished = 0; php_http_request_pool_reset(h); - php_http_persistent_handle_release(ZEND_STRL("http_request_pool.curl"), &curl->handle TSRMLS_CC); + + php_http_resource_factory_handle_dtor(h->rf, curl->handle); efree(curl); h->ctx = NULL; @@ -1349,14 +1454,16 @@ static int php_http_curl_request_pool_once(php_http_request_pool_t *h) return curl->unfinished; } +#ifdef PHP_HTTP_HAVE_EVENT static void dolog(int i, const char *m) { fprintf(stderr, "%d: %s\n", i, m); } +#endif static STATUS php_http_curl_request_pool_exec(php_http_request_pool_t *h) { +#ifdef PHP_HTTP_HAVE_EVENT php_http_curl_request_pool_t *curl = h->ctx; -#ifdef PHP_HTTP_HAVE_EVENT if (curl->useevents) { event_set_log_callback(dolog); do { @@ -1420,7 +1527,14 @@ static STATUS php_http_curl_request_pool_setopt(php_http_request_pool_t *h, php_ return SUCCESS; } +static php_http_resource_factory_ops_t php_http_curlm_resource_factory_ops = { + php_http_curlm_ctor, + NULL, + php_http_curlm_dtor +}; + static php_http_request_pool_ops_t php_http_curl_request_pool_ops = { + &php_http_curlm_resource_factory_ops, php_http_curl_request_pool_init, NULL /* copy */, php_http_curl_request_pool_dtor, @@ -1447,7 +1561,8 @@ static php_http_request_t *php_http_curl_request_init(php_http_request_t *h, voi php_http_curl_request_t *ctx; TSRMLS_FETCH_FROM_CTX(h->ts); - if (!handle && (SUCCESS != php_http_persistent_handle_acquire(ZEND_STRL("http_request.curl"), &handle TSRMLS_CC))) { + if (!handle && !(handle = php_http_resource_factory_handle_ctor(h->rf TSRMLS_CC))) { + php_http_error(HE_WARNING, PHP_HTTP_E_REQUEST, "could not initialize curl handle"); return NULL; } @@ -1485,14 +1600,14 @@ static php_http_request_t *php_http_curl_request_copy(php_http_request_t *from, void *copy; TSRMLS_FETCH_FROM_CTX(from->ts); - if (SUCCESS != php_http_persistent_handle_accrete(ZEND_STRL("http_request.curl"), ctx->handle, © TSRMLS_CC)) { + if (!(copy = php_http_resource_factory_handle_copy(from->rf, ctx->handle TSRMLS_CC))) { return NULL; } if (to) { return php_http_curl_request_init(to, copy); } else { - return php_http_request_init(NULL, from->ops, copy TSRMLS_CC); + return php_http_request_init(NULL, from->ops, from->rf, copy TSRMLS_CC); } } @@ -1505,7 +1620,7 @@ static void php_http_curl_request_dtor(php_http_request_t *h) curl_easy_setopt(ctx->handle, CURLOPT_VERBOSE, 0L); curl_easy_setopt(ctx->handle, CURLOPT_DEBUGFUNCTION, NULL); - php_http_persistent_handle_release(ZEND_STRL("http_request.curl"), &ctx->handle TSRMLS_CC); + php_http_resource_factory_handle_dtor(h->rf, ctx->handle TSRMLS_CC); php_http_buffer_dtor(&ctx->options.cookies); zend_hash_destroy(&ctx->options.cache); @@ -1514,11 +1629,7 @@ static void php_http_curl_request_dtor(php_http_request_t *h) curl_slist_free_all(ctx->options.headers); ctx->options.headers = NULL; } - - if (ctx->progress.callback) { - zval_ptr_dtor(&ctx->progress.callback); - ctx->progress.callback = NULL; - } + php_http_request_progress_dtor(&ctx->progress); efree(ctx); h->ctx = NULL; @@ -1714,19 +1825,12 @@ static STATUS php_http_curl_request_setopt(php_http_request_t *h, php_http_reque php_http_error(HE_WARNING, PHP_HTTP_E_REQUEST, "Cannot change progress callback while executing it"); return FAILURE; } - if (arg) { - Z_ADDREF_P(arg); - } if (curl->progress.callback) { - zval_ptr_dtor(&curl->progress.callback); + php_http_request_progress_dtor(&curl->progress TSRMLS_CC); } curl->progress.callback = arg; break; - case PHP_HTTP_REQUEST_OPT_PROGRESS_CALLBACK_WANTS_STATE: - curl->progress.pass_state = *((int *)arg); - break; - case PHP_HTTP_REQUEST_OPT_COOKIES_ENABLE: /* are cookies already enabled anyway? */ if (!get_storage(curl->handle)->cookiestore) { @@ -1781,7 +1885,14 @@ static STATUS php_http_curl_request_getopt(php_http_request_t *h, php_http_reque return SUCCESS; } +static php_http_resource_factory_ops_t php_http_curl_resource_factory_ops = { + php_http_curl_ctor, + php_http_curl_copy, + php_http_curl_dtor +}; + static php_http_request_ops_t php_http_curl_request_ops = { + &php_http_curl_resource_factory_ops, php_http_curl_request_init, php_http_curl_request_copy, php_http_curl_request_dtor, @@ -1796,45 +1907,6 @@ PHP_HTTP_API php_http_request_ops_t *php_http_curl_get_request_ops(void) return &php_http_curl_request_ops; } -/* safe curl wrappers */ -static void *safe_curl_init(void) -{ - void *ch; - - if ((ch = curl_easy_init())) { - get_storage(ch); - return ch; - } - return NULL; -} - -static void *safe_curl_copy(void *p) -{ - void *ch; - - if ((ch = curl_easy_duphandle(p))) { - get_storage(ch); - return ch; - } - return NULL; -} - -static void safe_curl_dtor(void *p) { - php_http_curl_request_storage_t *st = get_storage(p); - - curl_easy_cleanup(p); - - if (st) { - if (st->url) { - pefree(st->url, 1); - } - if (st->cookiestore) { - pefree(st->cookiestore, 1); - } - pefree(st, 1); - } -} - #if defined(ZTS) && defined(PHP_HTTP_HAVE_SSL) # ifdef PHP_WIN32 # define PHP_HTTP_NEED_OPENSSL_TSL @@ -1909,7 +1981,23 @@ static struct gcry_thread_cbs php_http_gnutls_tsl = { }; #endif +#define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpCURL, method, 0, req_args) +#define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpCURL, method, 0) +#define PHP_HTTP_CURL_ME(method, visibility) PHP_ME(HttpCURL, method, PHP_HTTP_ARGS(HttpCURL, method), visibility) +#define PHP_HTTP_CURL_ALIAS(method, func) PHP_HTTP_STATIC_ME_ALIAS(method, func, PHP_HTTP_ARGS(HttpCURL, method)) +#define PHP_HTTP_CURL_MALIAS(me, al, vis) ZEND_FENTRY(me, ZEND_MN(HttpCURL_##al), PHP_HTTP_ARGS(HttpCURL, al), vis) + +PHP_HTTP_EMPTY_ARGS(__construct); +zend_class_entry *php_http_curl_class_entry; +zend_function_entry php_http_curl_method_entry[] = { + PHP_HTTP_CURL_ME(__construct, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) + + EMPTY_FUNCTION_ENTRY +}; + +PHP_METHOD(HttpCURL, __construct) { +} PHP_MINIT_FUNCTION(http_curl) { @@ -1942,15 +2030,15 @@ PHP_MINIT_FUNCTION(http_curl) return FAILURE; } - if (SUCCESS != php_http_persistent_handle_provide(ZEND_STRL("http_request_datashare.curl"), curl_share_init, (php_http_persistent_handle_dtor_t) curl_share_cleanup, NULL TSRMLS_CC)) { + if (SUCCESS != php_http_persistent_handle_provide(ZEND_STRL("http_request_datashare.curl"), &php_http_curlsh_resource_factory_ops, NULL, NULL)) { return FAILURE; } - if (SUCCESS != php_http_persistent_handle_provide(ZEND_STRL("http_request_pool.curl"), curl_multi_init, (php_http_persistent_handle_dtor_t) curl_multi_cleanup, NULL TSRMLS_CC)) { + if (SUCCESS != php_http_persistent_handle_provide(ZEND_STRL("http_request_pool.curl"), &php_http_curlm_resource_factory_ops, NULL, NULL)) { return FAILURE; } - if (SUCCESS != php_http_persistent_handle_provide(ZEND_STRL("http_request.curl"), safe_curl_init, safe_curl_dtor, safe_curl_copy)) { + if (SUCCESS != php_http_persistent_handle_provide(ZEND_STRL("http_request.curl"), &php_http_curl_resource_factory_ops, NULL, NULL)) { return FAILURE; } @@ -1958,60 +2046,62 @@ PHP_MINIT_FUNCTION(http_curl) return FAILURE; } + PHP_HTTP_REGISTER_CLASS(http, CURL, http_curl, php_http_curl_class_entry, 0); + /* * HTTP Protocol Version Constants */ - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("VERSION_1_0"), CURL_HTTP_VERSION_1_0 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("VERSION_1_1"), CURL_HTTP_VERSION_1_1 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("VERSION_NONE"), CURL_HTTP_VERSION_NONE TSRMLS_CC); /* to be removed */ - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("VERSION_ANY"), CURL_HTTP_VERSION_NONE TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("HTTP_VERSION_1_0"), CURL_HTTP_VERSION_1_0 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("HTTP_VERSION_1_1"), CURL_HTTP_VERSION_1_1 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("HTTP_VERSION_NONE"), CURL_HTTP_VERSION_NONE TSRMLS_CC); /* to be removed */ + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("HTTP_VERSION_ANY"), CURL_HTTP_VERSION_NONE TSRMLS_CC); /* * SSL Version Constants */ - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("SSL_VERSION_TLSv1"), CURL_SSLVERSION_TLSv1 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("SSL_VERSION_SSLv2"), CURL_SSLVERSION_SSLv2 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("SSL_VERSION_SSLv3"), CURL_SSLVERSION_SSLv3 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("SSL_VERSION_ANY"), CURL_SSLVERSION_DEFAULT TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("SSL_VERSION_TLSv1"), CURL_SSLVERSION_TLSv1 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("SSL_VERSION_SSLv2"), CURL_SSLVERSION_SSLv2 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("SSL_VERSION_SSLv3"), CURL_SSLVERSION_SSLv3 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("SSL_VERSION_ANY"), CURL_SSLVERSION_DEFAULT TSRMLS_CC); /* * DNS IPvX resolving */ - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("IPRESOLVE_V4"), CURL_IPRESOLVE_V4 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("IPRESOLVE_V6"), CURL_IPRESOLVE_V6 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("IPRESOLVE_ANY"), CURL_IPRESOLVE_WHATEVER TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("IPRESOLVE_V4"), CURL_IPRESOLVE_V4 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("IPRESOLVE_V6"), CURL_IPRESOLVE_V6 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("IPRESOLVE_ANY"), CURL_IPRESOLVE_WHATEVER TSRMLS_CC); /* * Auth Constants */ - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("AUTH_BASIC"), CURLAUTH_BASIC TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("AUTH_DIGEST"), CURLAUTH_DIGEST TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("AUTH_BASIC"), CURLAUTH_BASIC TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("AUTH_DIGEST"), CURLAUTH_DIGEST TSRMLS_CC); #if PHP_HTTP_CURL_VERSION(7,19,3) - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("AUTH_DIGEST_IE"), CURLAUTH_DIGEST_IE TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("AUTH_DIGEST_IE"), CURLAUTH_DIGEST_IE TSRMLS_CC); #endif - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("AUTH_NTLM"), CURLAUTH_NTLM TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("AUTH_GSSNEG"), CURLAUTH_GSSNEGOTIATE TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("AUTH_ANY"), CURLAUTH_ANY TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("AUTH_NTLM"), CURLAUTH_NTLM TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("AUTH_GSSNEG"), CURLAUTH_GSSNEGOTIATE TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("AUTH_ANY"), CURLAUTH_ANY TSRMLS_CC); /* * Proxy Type Constants */ - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("PROXY_SOCKS4"), CURLPROXY_SOCKS4 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("PROXY_SOCKS4A"), CURLPROXY_SOCKS5 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("PROXY_SOCKS5_HOSTNAME"), CURLPROXY_SOCKS5 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("PROXY_SOCKS5"), CURLPROXY_SOCKS5 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("PROXY_HTTP"), CURLPROXY_HTTP TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("PROXY_SOCKS4"), CURLPROXY_SOCKS4 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("PROXY_SOCKS4A"), CURLPROXY_SOCKS5 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("PROXY_SOCKS5_HOSTNAME"), CURLPROXY_SOCKS5 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("PROXY_SOCKS5"), CURLPROXY_SOCKS5 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("PROXY_HTTP"), CURLPROXY_HTTP TSRMLS_CC); # if PHP_HTTP_CURL_VERSION(7,19,4) - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("PROXY_HTTP_1_0"), CURLPROXY_HTTP_1_0 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("PROXY_HTTP_1_0"), CURLPROXY_HTTP_1_0 TSRMLS_CC); # endif /* * Post Redirection Constants */ #if PHP_HTTP_CURL_VERSION(7,19,1) - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("POSTREDIR_301"), CURL_REDIR_POST_301 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("POSTREDIR_302"), CURL_REDIR_POST_302 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("POSTREDIR_ALL"), CURL_REDIR_POST_ALL TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("POSTREDIR_301"), CURL_REDIR_POST_301 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("POSTREDIR_302"), CURL_REDIR_POST_302 TSRMLS_CC); + zend_declare_class_constant_long(php_http_curl_class_entry, ZEND_STRL("POSTREDIR_ALL"), CURL_REDIR_POST_ALL TSRMLS_CC); #endif return SUCCESS; diff --git a/php_http_curl.h b/php_http_curl.h index 89f1948..6e9cc16 100644 --- a/php_http_curl.h +++ b/php_http_curl.h @@ -15,4 +15,11 @@ struct php_http_request_pool_globals { }; #endif +extern zend_class_entry *php_http_curl_class_entry; +extern zend_function_entry php_http_curl_method_entry[]; + +#define php_http_curl_new php_http_object_new + +PHP_METHOD(HttpCURL, __construct); + #endif diff --git a/php_http_encoding.c b/php_http_encoding.c index 93712c7..b7c994b 100644 --- a/php_http_encoding.c +++ b/php_http_encoding.c @@ -950,11 +950,11 @@ void php_http_encoding_stream_object_free(void *object TSRMLS_DC) PHP_METHOD(HttpEncodingStream, __construct) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { long flags = 0; if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(encoding)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { php_http_encoding_stream_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); if (!obj->stream) { diff --git a/php_http_neon.c b/php_http_neon.c index 5b26dfc..11117d3 100644 --- a/php_http_neon.c +++ b/php_http_neon.c @@ -143,58 +143,34 @@ static void php_http_neon_progress_callback(void *ctx, ne_session_status status, { php_http_request_t *h = ctx; php_http_neon_request_t *neon = h->ctx; + TSRMLS_FETCH_FROM_CTX(h->ts); switch (status) { case ne_status_lookup: + neon->progress.state.info = "resolve"; break; case ne_status_connecting: + neon->progress.state.info = "connect"; break; case ne_status_connected: + neon->progress.state.info = "connected"; break; case ne_status_sending: + neon->progress.state.info = "send"; neon->progress.state.ul.total = info->sr.total; neon->progress.state.ul.now = info->sr.progress; break; case ne_status_recving: + neon->progress.state.info = "receive"; neon->progress.state.dl.total = info->sr.total; neon->progress.state.dl.now = info->sr.progress; break; case ne_status_disconnected: + neon->progress.state.info = "disconnected"; break; } - if (neon->progress.callback) { - zval retval; - TSRMLS_FETCH_FROM_CTX(h->ts); - - INIT_PZVAL(&retval); - ZVAL_NULL(&retval); - - with_error_handling(EH_NORMAL, NULL) { - if (neon->progress.pass_state) { - zval *param; - - MAKE_STD_ZVAL(param); - array_init(param); - add_assoc_double(param, "dltotal", neon->progress.state.dl.total); - add_assoc_double(param, "dlnow", neon->progress.state.dl.now); - add_assoc_double(param, "ultotal", neon->progress.state.ul.total); - add_assoc_double(param, "ulnow", neon->progress.state.ul.now); - - neon->progress.in_cb = 1; - call_user_function(EG(function_table), NULL, neon->progress.callback, &retval, 1, ¶m TSRMLS_CC); - neon->progress.in_cb = 0; - - zval_ptr_dtor(¶m); - } else { - neon->progress.in_cb = 1; - call_user_function(EG(function_table), NULL, neon->progress.callback, &retval, 0, NULL TSRMLS_CC); - neon->progress.in_cb = 0; - } - } end_error_handling(); - - zval_dtor(&retval); - } + php_http_request_progress_notify(&neon->progress TSRMLS_CC); } /* helpers */ @@ -219,7 +195,7 @@ static inline zval *get_option(HashTable *cache, HashTable *options, char *key, ulong h = zend_hash_func(key, keylen); if (SUCCESS == zend_hash_quick_find(options, key, keylen, h, (void *) &zoption)) { - zval *option = php_http_zsep(type, *zoption); + zval *option = php_http_ztyp(type, *zoption); if (cache) { zval *cached = cache_option(cache, key, keylen, h, option); @@ -361,8 +337,8 @@ static STATUS set_options(php_http_request_t *h, HashTable *options) if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr), (void *) &re, &pos2)) { if ( ((Z_TYPE_PP(rb) == IS_LONG) || ((Z_TYPE_PP(rb) == IS_STRING) && is_numeric_string(Z_STRVAL_PP(rb), Z_STRLEN_PP(rb), NULL, NULL, 1))) && ((Z_TYPE_PP(re) == IS_LONG) || ((Z_TYPE_PP(re) == IS_STRING) && is_numeric_string(Z_STRVAL_PP(re), Z_STRLEN_PP(re), NULL, NULL, 1)))) { - zval *rbl = php_http_zsep(IS_LONG, *rb); - zval *rel = php_http_zsep(IS_LONG, *re); + zval *rbl = php_http_ztyp(IS_LONG, *rb); + zval *rel = php_http_ztyp(IS_LONG, *re); if ((Z_LVAL_P(rbl) >= 0) && (Z_LVAL_P(rel) >= 0)) { php_http_buffer_appendf(&rs, "%ld-%ld,", Z_LVAL_P(rbl), Z_LVAL_P(rel)); @@ -391,7 +367,7 @@ static STATUS set_options(php_http_request_t *h, HashTable *options) FOREACH_KEYVAL(pos, zoption, header_key, header_val) { if (header_key.type == HASH_KEY_IS_STRING) { - zval *header_cpy = php_http_zsep(IS_STRING, *header_val); + zval *header_cpy = php_http_ztyp(IS_STRING, *header_val); if (!strcasecmp(header_key.str, "range")) { range_req = 1; @@ -455,7 +431,7 @@ static STATUS set_options(php_http_request_t *h, HashTable *options) FOREACH_KEYVAL(pos, zoption, cookie_key, cookie_val) { if (cookie_key.type == HASH_KEY_IS_STRING) { - zval *val = php_http_zsep(IS_STRING, *cookie_val); + zval *val = php_http_ztyp(IS_STRING, *cookie_val); php_http_buffer_appendf(&neon->options.headers, "%s=%s; ", cookie_key.str, Z_STRVAL_P(val)); zval_ptr_dtor(&val); } @@ -494,13 +470,13 @@ static STATUS set_options(php_http_request_t *h, HashTable *options) } } if (SUCCESS == zend_hash_find(Z_ARRVAL_P(zoption), ZEND_STRS("key"), (void *) &zssl)) { - zval *cpy = php_http_zsep(IS_STRING, *zssl); + zval *cpy = php_http_ztyp(IS_STRING, *zssl); ne_ssl_client_cert *cc = ne_ssl_clicert_read(Z_STRVAL_P(cpy)); if (cc) { if (ne_ssl_clicert_encrypted(cc)) { if (SUCCESS == zend_hash_find(Z_ARRVAL_P(zoption), ZEND_STRS("keypasswd"), (void *) &zssl)) { - zval *cpy = php_http_zsep(IS_STRING, *zssl); + zval *cpy = php_http_ztyp(IS_STRING, *zssl); if (NE_OK == ne_ssl_clicert_decrypt(cc, Z_STRVAL_P(cpy))) { neon->options.ssl.clicert = cc; @@ -517,7 +493,7 @@ static STATUS set_options(php_http_request_t *h, HashTable *options) zval_ptr_dtor(&cpy); } if (SUCCESS == zend_hash_find(Z_ARRVAL_P(zoption), ZEND_STRS("cert"), (void *) &zssl)) { - zval *cpy = php_http_zsep(IS_STRING, *zssl); + zval *cpy = php_http_ztyp(IS_STRING, *zssl); ne_ssl_certificate *tc = ne_ssl_cert_read(Z_STRVAL_P(cpy)); if (tc) { @@ -553,7 +529,7 @@ static php_http_request_t *php_http_neon_request_copy(php_http_request_t *from, if (to) { return php_http_neon_request_init(to, NULL); } else { - return php_http_request_init(NULL, from->ops, NULL TSRMLS_CC); + return php_http_request_init(NULL, from->ops, from->rf, NULL TSRMLS_CC); } } @@ -565,6 +541,8 @@ static void php_http_neon_request_dtor(php_http_request_t *h) php_http_buffer_dtor(&ctx->options.headers); zend_hash_destroy(&ctx->options.cache); + php_http_request_progress_dtor(&ctx->progress); + efree(ctx); h->ctx = NULL; } @@ -607,15 +585,7 @@ static STATUS php_http_neon_request_reset(php_http_request_t *h) neon->options.timeout.read = 0; neon->options.timeout.connect = 0; - if (neon->progress.callback) { - zval_ptr_dtor(&neon->progress.callback); - neon->progress.callback = NULL; - } - neon->progress.pass_state = 0; - neon->progress.state.dl.now = 0; - neon->progress.state.dl.total = 0; - neon->progress.state.ul.now = 0; - neon->progress.state.ul.total = 0; + php_http_request_progress_dtor(&neon->progress); return SUCCESS; } @@ -645,20 +615,21 @@ static STATUS php_http_neon_request_exec(php_http_request_t *h, php_http_request if (neon->options.port) { purl->port = neon->options.port; } else if (!purl->port) { + purl->port = 80; + if (strncascmp(purl->scheme, "http", 4)) { #ifdef HAVE_GETSERVBYNAME - struct servent *se; + struct servent *se; - if ((se = getservbyname(purl->scheme, "tcp")) && se->s_port) { - purl->port = ntohs(se->s_port); - } else + if ((se = getservbyname(purl->scheme, "tcp")) && se->s_port) { + purl->port = ntohs(se->s_port); + } #endif - if (!strcasecmp(purl->scheme, "https")) { + } else if (purl->scheme[4] == 's') { purl->port = 443; - } else { - purl->port = 80; } } + /* never returns NULL */ session = ne_session_create(purl->scheme, purl->host, purl->port); if (neon->options.proxy.host) { switch (neon->options.proxy.type) { @@ -793,16 +764,14 @@ static STATUS php_http_neon_request_setopt(php_http_request_t *h, php_http_reque break; case PHP_HTTP_REQUEST_OPT_PROGRESS_CALLBACK: - if (neon->progress.callback) { - zval_ptr_dtor(&neon->progress.callback); + if (neon->progress.in_cb) { + php_http_error(HE_WARNING, PHP_HTTP_E_REQUEST, "Cannot change progress callback while executing it"); + return FAILURE; } - if ((neon->progress.callback = arg)) { - Z_ADDREF_P(neon->progress.callback); + if (neon->progress.callback) { + php_http_request_progress_dtor(&neon->progress TSRMLS_CC); } - break; - - case PHP_HTTP_REQUEST_OPT_PROGRESS_CALLBACK_WANTS_STATE: - neon->progress.pass_state = *((int *)arg); + neon->progress.callback = arg; break; case PHP_HTTP_REQUEST_OPT_COOKIES_ENABLE: @@ -825,7 +794,7 @@ static STATUS php_http_neon_request_getopt(php_http_request_t *h, php_http_reque switch (opt) { case PHP_HTTP_REQUEST_OPT_PROGRESS_INFO: - memcpy(arg, &neon->progress, sizeof(neon->progress)); + *((php_http_request_progress_t **) arg) = &neon->progress; break; case PHP_HTTP_REQUEST_OPT_TRANSFER_INFO: @@ -838,7 +807,14 @@ static STATUS php_http_neon_request_getopt(php_http_request_t *h, php_http_reque return SUCCESS; } +static php_http_resource_factory_ops_t php_http_neon_resource_factory_ops = { + NULL, + NULL, + NULL +}; + static php_http_request_ops_t php_http_neon_request_ops = { + &php_http_neon_resource_factory_ops, php_http_neon_request_init, php_http_neon_request_copy, php_http_neon_request_dtor, @@ -853,6 +829,25 @@ PHP_HTTP_API php_http_request_ops_t *php_http_neon_get_request_ops(void) return &php_http_neon_request_ops; } +#define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpNEON, method, 0, req_args) +#define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpNEON, method, 0) +#define PHP_HTTP_NEON_ME(method, visibility) PHP_ME(HttpNEON, method, PHP_HTTP_ARGS(HttpNEON, method), visibility) +#define PHP_HTTP_NEON_ALIAS(method, func) PHP_HTTP_STATIC_ME_ALIAS(method, func, PHP_HTTP_ARGS(HttpNEON, method)) +#define PHP_HTTP_NEON_MALIAS(me, al, vis) ZEND_FENTRY(me, ZEND_MN(HttpNEON_##al), PHP_HTTP_ARGS(HttpNEON, al), vis) + +PHP_HTTP_EMPTY_ARGS(__construct); + +zend_class_entry *php_http_neon_class_entry; +zend_function_entry php_http_neon_method_entry[] = { + PHP_HTTP_NEON_ME(__construct, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) + + EMPTY_FUNCTION_ENTRY +}; + +PHP_METHOD(HttpNEON, __construct) { +} + + PHP_MINIT_FUNCTION(http_neon) { php_http_request_factory_driver_t driver = { @@ -863,22 +858,25 @@ PHP_MINIT_FUNCTION(http_neon) return FAILURE; } + PHP_HTTP_REGISTER_CLASS(http, NEON, http_neon, php_http_neon_class_entry, 0); + /* * Auth Constants */ - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("AUTH_BASIC"), NE_AUTH_BASIC TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("AUTH_DIGEST"), NE_AUTH_DIGEST TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("AUTH_NTLM"), NE_AUTH_NTLM TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("AUTH_GSSNEG"), NE_AUTH_GSSAPI TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("AUTH_ANY"), NE_AUTH_ALL TSRMLS_CC); + zend_declare_class_constant_long(php_http_neon_class_entry, ZEND_STRL("AUTH_BASIC"), NE_AUTH_BASIC TSRMLS_CC); + zend_declare_class_constant_long(php_http_neon_class_entry, ZEND_STRL("AUTH_DIGEST"), NE_AUTH_DIGEST TSRMLS_CC); + zend_declare_class_constant_long(php_http_neon_class_entry, ZEND_STRL("AUTH_NTLM"), NE_AUTH_NTLM TSRMLS_CC); + zend_declare_class_constant_long(php_http_neon_class_entry, ZEND_STRL("AUTH_GSSAPI"), NE_AUTH_GSSAPI TSRMLS_CC); + zend_declare_class_constant_long(php_http_neon_class_entry, ZEND_STRL("AUTH_GSSNEG"), NE_AUTH_NEGOTIATE TSRMLS_CC); + zend_declare_class_constant_long(php_http_neon_class_entry, ZEND_STRL("AUTH_ANY"), NE_AUTH_ALL TSRMLS_CC); /* * Proxy Type Constants */ - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("PROXY_SOCKS4"), NE_SOCK_SOCKSV4 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("PROXY_SOCKS4A"), NE_SOCK_SOCKSV4A TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("PROXY_SOCKS5"), NE_SOCK_SOCKSV5 TSRMLS_CC); - zend_declare_class_constant_long(php_http_request_class_entry, ZEND_STRL("PROXY_HTTP"), -1 TSRMLS_CC); + zend_declare_class_constant_long(php_http_neon_class_entry, ZEND_STRL("PROXY_SOCKS4"), NE_SOCK_SOCKSV4 TSRMLS_CC); + zend_declare_class_constant_long(php_http_neon_class_entry, ZEND_STRL("PROXY_SOCKS4A"), NE_SOCK_SOCKSV4A TSRMLS_CC); + zend_declare_class_constant_long(php_http_neon_class_entry, ZEND_STRL("PROXY_SOCKS5"), NE_SOCK_SOCKSV5 TSRMLS_CC); + zend_declare_class_constant_long(php_http_neon_class_entry, ZEND_STRL("PROXY_HTTP"), -1 TSRMLS_CC); if (NE_OK != ne_sock_init()) { return FAILURE; diff --git a/php_http_neon.h b/php_http_neon.h index 96b7d0d..dd4ff98 100644 --- a/php_http_neon.h +++ b/php_http_neon.h @@ -6,4 +6,11 @@ php_http_request_ops_t *php_http_neon_get_request_ops(void); PHP_MINIT_FUNCTION(http_neon); PHP_MSHUTDOWN_FUNCTION(http_neon); +extern zend_class_entry *php_http_neon_class_entry; +extern zend_function_entry php_http_neon_method_entry[]; + +#define php_http_neon_new php_http_object_new + +PHP_METHOD(HttpNEON, __construct); + #endif /* PHP_HTTP_NEON_H */ diff --git a/php_http_persistent_handle.c b/php_http_persistent_handle.c index a5f9689..55d53d0 100644 --- a/php_http_persistent_handle.c +++ b/php_http_persistent_handle.c @@ -39,9 +39,7 @@ typedef struct php_http_persistent_handle_list { typedef struct php_http_persistent_handle_provider { php_http_persistent_handle_list_t list; /* "ident" => array(handles) entries */ - php_http_persistent_handle_ctor_t ctor; - php_http_persistent_handle_dtor_t dtor; - php_http_persistent_handle_copy_t copy; + php_http_resource_factory_t rf; } php_http_persistent_handle_provider_t; static inline php_http_persistent_handle_list_t *php_http_persistent_handle_list_init(php_http_persistent_handle_list_t *list) @@ -64,7 +62,7 @@ static inline php_http_persistent_handle_list_t *php_http_persistent_handle_list return list; } -static inline void php_http_persistent_handle_list_dtor(php_http_persistent_handle_list_t *list, php_http_persistent_handle_dtor_t dtor) +static inline void php_http_persistent_handle_list_dtor(php_http_persistent_handle_list_t *list, php_http_persistent_handle_provider_t *provider TSRMLS_DC) { HashPosition pos; void **handle; @@ -77,14 +75,14 @@ static inline void php_http_persistent_handle_list_dtor(php_http_persistent_hand fprintf(stderr, "DESTROY: %p\n", *handle); #endif - dtor(*handle); + provider->rf.fops.dtor(provider->rf.data, *handle TSRMLS_CC); } zend_hash_destroy(&list->free); } -static inline void php_http_persistent_handle_list_free(php_http_persistent_handle_list_t **list, php_http_persistent_handle_dtor_t dtor) +static inline void php_http_persistent_handle_list_free(php_http_persistent_handle_list_t **list, php_http_persistent_handle_provider_t *provider TSRMLS_DC) { - php_http_persistent_handle_list_dtor(*list, dtor); + php_http_persistent_handle_list_dtor(*list, provider TSRMLS_CC); #if PHP_HTTP_DEBUG_PHANDLES fprintf(stderr, "LSTFREE: %p\n", *list); #endif @@ -92,11 +90,11 @@ static inline void php_http_persistent_handle_list_free(php_http_persistent_hand *list = NULL; } -static inline php_http_persistent_handle_list_t *php_http_persistent_handle_list_find(php_http_persistent_handle_provider_t *provider TSRMLS_DC) +static inline php_http_persistent_handle_list_t *php_http_persistent_handle_list_find(php_http_persistent_handle_provider_t *provider, const char *ident_str, size_t ident_len TSRMLS_DC) { php_http_persistent_handle_list_t **list, *new_list; - if (SUCCESS == zend_hash_quick_find(&provider->list.free, PHP_HTTP_G->persistent_handle.ident.s, PHP_HTTP_G->persistent_handle.ident.l, PHP_HTTP_G->persistent_handle.ident.h, (void *) &list)) { + if (SUCCESS == zend_hash_find(&provider->list.free, ident_str, ident_len + 1, (void *) &list)) { #if PHP_HTTP_DEBUG_PHANDLES fprintf(stderr, "LSTFIND: %p\n", *list); #endif @@ -104,31 +102,31 @@ static inline php_http_persistent_handle_list_t *php_http_persistent_handle_list } if ((new_list = php_http_persistent_handle_list_init(NULL))) { - if (SUCCESS == zend_hash_quick_add(&provider->list.free, PHP_HTTP_G->persistent_handle.ident.s, PHP_HTTP_G->persistent_handle.ident.l, PHP_HTTP_G->persistent_handle.ident.h, (void *) &new_list, sizeof(php_http_persistent_handle_list_t *), (void *) &list)) { + if (SUCCESS == zend_hash_add(&provider->list.free, ident_str, ident_len + 1, (void *) &new_list, sizeof(php_http_persistent_handle_list_t *), (void *) &list)) { #if PHP_HTTP_DEBUG_PHANDLES fprintf(stderr, "LSTFIND: %p (new)\n", *list); #endif return *list; } - php_http_persistent_handle_list_free(&new_list, provider->dtor); + php_http_persistent_handle_list_free(&new_list, provider TSRMLS_CC); } return NULL; } -static inline STATUS php_http_persistent_handle_do_acquire(php_http_persistent_handle_provider_t *provider, void **handle TSRMLS_DC) +static inline STATUS php_http_persistent_handle_do_acquire(php_http_persistent_handle_provider_t *provider, const char *ident_str, size_t ident_len, void **handle TSRMLS_DC) { ulong index; void **handle_ptr; php_http_persistent_handle_list_t *list; - if ((list = php_http_persistent_handle_list_find(provider TSRMLS_CC))) { + if ((list = php_http_persistent_handle_list_find(provider, ident_str, ident_len TSRMLS_CC))) { zend_hash_internal_pointer_end(&list->free); if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(&list->free, NULL, &index, 0) && SUCCESS == zend_hash_get_current_data(&list->free, (void *) &handle_ptr)) { *handle = *handle_ptr; zend_hash_index_del(&list->free, index); } else { - *handle = provider->ctor(); + *handle = provider->rf.fops.ctor(provider->rf.data TSRMLS_CC); } if (*handle) { @@ -143,13 +141,13 @@ static inline STATUS php_http_persistent_handle_do_acquire(php_http_persistent_h return FAILURE; } -static inline STATUS php_http_persistent_handle_do_release(php_http_persistent_handle_provider_t *provider, void **handle TSRMLS_DC) +static inline STATUS php_http_persistent_handle_do_release(php_http_persistent_handle_provider_t *provider, const char *ident_str, size_t ident_len, void **handle TSRMLS_DC) { php_http_persistent_handle_list_t *list; - if ((list = php_http_persistent_handle_list_find(provider TSRMLS_CC))) { + if ((list = php_http_persistent_handle_list_find(provider, ident_str, ident_len TSRMLS_CC))) { if (provider->list.used >= PHP_HTTP_G->persistent_handle.limit) { - provider->dtor(*handle); + provider->rf.fops.dtor(provider->rf.data, *handle TSRMLS_CC); } else { if (SUCCESS != zend_hash_next_index_insert(&list->free, (void *) handle, sizeof(void *), NULL)) { return FAILURE; @@ -165,12 +163,12 @@ static inline STATUS php_http_persistent_handle_do_release(php_http_persistent_h return FAILURE; } -static inline STATUS php_http_persistent_handle_do_accrete(php_http_persistent_handle_provider_t *provider, void *old_handle, void **new_handle TSRMLS_DC) +static inline STATUS php_http_persistent_handle_do_accrete(php_http_persistent_handle_provider_t *provider, const char *ident_str, size_t ident_len, void *old_handle, void **new_handle TSRMLS_DC) { php_http_persistent_handle_list_t *list; - if (provider->copy && (*new_handle = provider->copy(old_handle))) { - if ((list = php_http_persistent_handle_list_find(provider TSRMLS_CC))) { + if (provider->rf.fops.copy && (*new_handle = provider->rf.fops.copy(provider->rf.data, old_handle TSRMLS_CC))) { + if ((list = php_http_persistent_handle_list_find(provider, ident_str, ident_len TSRMLS_CC))) { ++list->used; } ++provider->list.used; @@ -188,10 +186,11 @@ static void php_http_persistent_handles_hash_dtor(void *p) FOREACH_HASH_VAL(pos, &provider->list.free, list) { /* fix shutdown crash in PHP4 */ list_tmp = *list; - php_http_persistent_handle_list_free(&list_tmp, provider->dtor); + php_http_persistent_handle_list_free(&list_tmp, provider TSRMLS_CC); } zend_hash_destroy(&provider->list.free); + php_http_resource_factory_dtor(&provider->rf); } PHP_MINIT_FUNCTION(http_persistent_handle) @@ -212,23 +211,23 @@ PHP_MSHUTDOWN_FUNCTION(http_persistent_handle) return SUCCESS; } -PHP_HTTP_API STATUS php_http_persistent_handle_provide(const char *name_str, size_t name_len, php_http_persistent_handle_ctor_t ctor, php_http_persistent_handle_dtor_t dtor, php_http_persistent_handle_copy_t copy) +PHP_HTTP_API STATUS php_http_persistent_handle_provide(const char *name_str, size_t name_len, php_http_resource_factory_ops_t *fops, void *data, void (*dtor)(void *)) { STATUS status = FAILURE; php_http_persistent_handle_provider_t provider; LOCK(); if (php_http_persistent_handle_list_init(&provider.list)) { - provider.ctor = ctor; - provider.dtor = dtor; - provider.copy = copy; - + if (php_http_resource_factory_init(&provider.rf, fops, data, dtor)) { #if PHP_HTTP_DEBUG_PHANDLES - fprintf(stderr, "PROVIDE: %s\n", name_str); + fprintf(stderr, "PROVIDE: %s\n", name_str); #endif - if (SUCCESS == zend_hash_add(&php_http_persistent_handles_hash, name_str, name_len+1, (void *) &provider, sizeof(php_http_persistent_handle_provider_t), NULL)) { - status = SUCCESS; + if (SUCCESS == zend_hash_add(&php_http_persistent_handles_hash, name_str, name_len+1, (void *) &provider, sizeof(php_http_persistent_handle_provider_t), NULL)) { + status = SUCCESS; + } else { + php_http_resource_factory_dtor(&provider.rf); + } } } UNLOCK(); @@ -236,7 +235,80 @@ PHP_HTTP_API STATUS php_http_persistent_handle_provide(const char *name_str, siz return status; } -PHP_HTTP_API STATUS php_http_persistent_handle_acquire(const char *name_str, size_t name_len, void **handle TSRMLS_DC) +PHP_HTTP_API php_http_persistent_handle_factory_t *php_http_persistent_handle_concede(php_http_persistent_handle_factory_t *a, const char *name_str, size_t name_len, const char *ident_str, size_t ident_len TSRMLS_DC) +{ + STATUS status = FAILURE; + php_http_persistent_handle_factory_t *free_a = NULL; + + if (!a) { + free_a = a = emalloc(sizeof(*a)); + } + memset(a, 0, sizeof(*a)); + + LOCK(); + status = zend_hash_find(&php_http_persistent_handles_hash, name_str, name_len+1, (void *) &a->provider); + UNLOCK(); + + if (SUCCESS == status) { + a->ident.str = estrndup(ident_str, a->ident.len = ident_len); + if (free_a) { + a->free_on_abandon = 1; + } + } else { + if (free_a) { + efree(a); + } + a = NULL; + } + +#if PHP_HTTP_DEBUG_PHANDLES + fprintf(stderr, "CONCETE: %p (%s) (%s)\n", a ? a->provider : NULL, name_str, ident_str); +#endif + + return a; +} + +PHP_HTTP_API void php_http_persistent_handle_abandon(php_http_persistent_handle_factory_t *a) +{ + zend_bool f = a->free_on_abandon; + + STR_FREE(a->ident.str); + memset(a, 0, sizeof(*a)); + if (f) { + efree(a); + } +} + +PHP_HTTP_API void *php_http_persistent_handle_acquire(php_http_persistent_handle_factory_t *a TSRMLS_DC) +{ + void *handle = NULL; + + LOCK(); + php_http_persistent_handle_do_acquire(a->provider, a->ident.str, a->ident.len, &handle TSRMLS_CC); + UNLOCK(); + + return handle; +} + +PHP_HTTP_API void *php_http_persistent_handle_accrete(php_http_persistent_handle_factory_t *a, void *handle TSRMLS_DC) +{ + void *new_handle; + + LOCK(); + php_http_persistent_handle_do_accrete(a->provider, a->ident.str, a->ident.len, handle, &new_handle TSRMLS_CC); + UNLOCK(); + + return new_handle; +} + +PHP_HTTP_API void php_http_persistent_handle_release(php_http_persistent_handle_factory_t *a, void *handle TSRMLS_DC) +{ + LOCK(); + php_http_persistent_handle_do_release(a->provider, a->ident.str, a->ident.len, &handle); + UNLOCK(); +} + +PHP_HTTP_API STATUS php_http_persistent_handle_acquire2(const char *name_str, size_t name_len, const char *ident_str, size_t ident_len, void **handle TSRMLS_DC) { STATUS status = FAILURE; php_http_persistent_handle_provider_t *provider; @@ -244,7 +316,7 @@ PHP_HTTP_API STATUS php_http_persistent_handle_acquire(const char *name_str, siz *handle = NULL; LOCK(); if (SUCCESS == zend_hash_find(&php_http_persistent_handles_hash, name_str, name_len+1, (void *) &provider)) { - status = php_http_persistent_handle_do_acquire(provider, handle TSRMLS_CC); + status = php_http_persistent_handle_do_acquire(provider, ident_str, ident_len, handle TSRMLS_CC); } UNLOCK(); @@ -255,7 +327,7 @@ PHP_HTTP_API STATUS php_http_persistent_handle_acquire(const char *name_str, siz return status; } -PHP_HTTP_API STATUS php_http_persistent_handle_release(const char *name_str, size_t name_len, void **handle TSRMLS_DC) +PHP_HTTP_API STATUS php_http_persistent_handle_release2(const char *name_str, size_t name_len, const char *ident_str, size_t ident_len, void **handle TSRMLS_DC) { STATUS status = FAILURE; php_http_persistent_handle_provider_t *provider; @@ -265,7 +337,7 @@ PHP_HTTP_API STATUS php_http_persistent_handle_release(const char *name_str, siz LOCK(); if (SUCCESS == zend_hash_find(&php_http_persistent_handles_hash, name_str, name_len+1, (void *) &provider)) { - status = php_http_persistent_handle_do_release(provider, handle TSRMLS_CC); + status = php_http_persistent_handle_do_release(provider, ident_str, ident_len, handle TSRMLS_CC); } UNLOCK(); @@ -276,7 +348,7 @@ PHP_HTTP_API STATUS php_http_persistent_handle_release(const char *name_str, siz return status; } -PHP_HTTP_API STATUS php_http_persistent_handle_accrete(const char *name_str, size_t name_len, void *old_handle, void **new_handle TSRMLS_DC) +PHP_HTTP_API STATUS php_http_persistent_handle_accrete2(const char *name_str, size_t name_len, const char *ident_str, size_t ident_len, void *old_handle, void **new_handle TSRMLS_DC) { STATUS status = FAILURE; php_http_persistent_handle_provider_t *provider; @@ -284,7 +356,7 @@ PHP_HTTP_API STATUS php_http_persistent_handle_accrete(const char *name_str, siz *new_handle = NULL; LOCK(); if (SUCCESS == zend_hash_find(&php_http_persistent_handles_hash, name_str, name_len+1, (void *) &provider)) { - status = php_http_persistent_handle_do_accrete(provider, old_handle, new_handle TSRMLS_CC); + status = php_http_persistent_handle_do_accrete(provider, ident_str, ident_len, old_handle, new_handle TSRMLS_CC); } UNLOCK(); @@ -295,7 +367,7 @@ PHP_HTTP_API STATUS php_http_persistent_handle_accrete(const char *name_str, siz return status; } -PHP_HTTP_API void php_http_persistent_handle_cleanup(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC) +PHP_HTTP_API void php_http_persistent_handle_cleanup(const char *name_str, size_t name_len, const char *ident_str, size_t ident_len TSRMLS_DC) { php_http_persistent_handle_provider_t *provider; php_http_persistent_handle_list_t *list, **listp; @@ -304,28 +376,28 @@ PHP_HTTP_API void php_http_persistent_handle_cleanup(const char *name_str, size_ LOCK(); if (name_str && name_len) { if (SUCCESS == zend_hash_find(&php_http_persistent_handles_hash, name_str, name_len+1, (void *) &provider)) { - if (current_ident_only) { - if ((list = php_http_persistent_handle_list_find(provider TSRMLS_CC))) { - php_http_persistent_handle_list_dtor(list, provider->dtor); + if (ident_str && ident_len) { + if ((list = php_http_persistent_handle_list_find(provider, ident_str, ident_len TSRMLS_CC))) { + php_http_persistent_handle_list_dtor(list, provider TSRMLS_CC); php_http_persistent_handle_list_init(list); } } else { FOREACH_HASH_VAL(pos1, &provider->list.free, listp) { - php_http_persistent_handle_list_dtor(*listp, provider->dtor); + php_http_persistent_handle_list_dtor(*listp, provider TSRMLS_CC); php_http_persistent_handle_list_init(*listp); } } } } else { FOREACH_HASH_VAL(pos1, &php_http_persistent_handles_hash, provider) { - if (current_ident_only) { - if ((list = php_http_persistent_handle_list_find(provider TSRMLS_CC))) { - php_http_persistent_handle_list_dtor(list, provider->dtor); + if (ident_str && ident_len) { + if ((list = php_http_persistent_handle_list_find(provider, ident_str, ident_len TSRMLS_CC))) { + php_http_persistent_handle_list_dtor(list, provider TSRMLS_CC); php_http_persistent_handle_list_init(list); } } else { FOREACH_HASH_VAL(pos2, &provider->list.free, listp) { - php_http_persistent_handle_list_dtor(*listp, provider->dtor); + php_http_persistent_handle_list_dtor(*listp, provider TSRMLS_CC); php_http_persistent_handle_list_init(*listp); } } diff --git a/php_http_persistent_handle.h b/php_http_persistent_handle.h index 075fe92..07aa796 100644 --- a/php_http_persistent_handle.h +++ b/php_http_persistent_handle.h @@ -15,9 +15,18 @@ #ifndef PHP_HTTP_PERSISTENT_HANDLE_H #define PHP_HTTP_PERSISTENT_HANDLE_H -typedef void *(*php_http_persistent_handle_ctor_t)(void); -typedef void (*php_http_persistent_handle_dtor_t)(void *handle); -typedef void *(*php_http_persistent_handle_copy_t)(void *handle); +#include "php_http_resource_factory.h" + +typedef struct php_http_persistent_handle_factory { + void *provider; + + struct { + char *str; + size_t len; + } ident; + + unsigned free_on_abandon:1; +} php_http_persistent_handle_factory_t; struct php_http_persistent_handle_globals { ulong limit; @@ -31,12 +40,21 @@ struct php_http_persistent_handle_globals { PHP_MINIT_FUNCTION(http_persistent_handle); PHP_MSHUTDOWN_FUNCTION(http_persistent_handle); -PHP_HTTP_API STATUS php_http_persistent_handle_provide(const char *name_str, size_t name_len, php_http_persistent_handle_ctor_t ctor, php_http_persistent_handle_dtor_t dtor, php_http_persistent_handle_copy_t copy); -PHP_HTTP_API void php_http_persistent_handle_cleanup(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC); +PHP_HTTP_API STATUS php_http_persistent_handle_provide(const char *name_str, size_t name_len, php_http_resource_factory_ops_t *fops, void *data, void (*dtor)(void *)); +PHP_HTTP_API php_http_persistent_handle_factory_t *php_http_persistent_handle_concede(php_http_persistent_handle_factory_t *a, const char *name_str, size_t name_len, const char *ident_str, size_t ident_len TSRMLS_DC); +PHP_HTTP_API void php_http_persistent_handle_abandon(php_http_persistent_handle_factory_t *a); +PHP_HTTP_API void *php_http_persistent_handle_acquire(php_http_persistent_handle_factory_t *a TSRMLS_DC); +PHP_HTTP_API void php_http_persistent_handle_release(php_http_persistent_handle_factory_t *a, void *handle TSRMLS_DC); +PHP_HTTP_API void *php_http_persistent_handle_accrete(php_http_persistent_handle_factory_t *a, void *handle TSRMLS_DC); + +PHP_HTTP_API php_http_resource_factory_ops_t *php_http_persistnet_handle_factory_ops(void); + +PHP_HTTP_API void php_http_persistent_handle_cleanup(const char *name_str, size_t name_len, const char *ident_str, size_t ident_len TSRMLS_DC); PHP_HTTP_API HashTable *php_http_persistent_handle_statall(HashTable *ht TSRMLS_DC); -PHP_HTTP_API STATUS php_http_persistent_handle_acquire(const char *name_str, size_t name_len, void **handle TSRMLS_DC); -PHP_HTTP_API STATUS php_http_persistent_handle_release(const char *name_str, size_t name_len, void **handle TSRMLS_DC); -PHP_HTTP_API STATUS php_http_persistent_handle_accrete(const char *name_str, size_t name_len, void *old_handle, void **new_handle TSRMLS_DC); + +PHP_HTTP_API STATUS php_http_persistent_handle_acquire2(const char *name_str, size_t name_len, const char *ident_str, size_t ident_len, void **handle TSRMLS_DC); +PHP_HTTP_API STATUS php_http_persistent_handle_release2(const char *name_str, size_t name_len, const char *ident_str, size_t ident_len, void **handle TSRMLS_DC); +PHP_HTTP_API STATUS php_http_persistent_handle_accrete2(const char *name_str, size_t name_len, const char *ident_str, size_t ident_len, void *old_handle, void **new_handle TSRMLS_DC); #endif /* PHP_HTTP_PERSISTENT_HANDLE_H */ diff --git a/php_http_request.c b/php_http_request.c index 63d68db..6b8d444 100644 --- a/php_http_request.c +++ b/php_http_request.c @@ -19,7 +19,7 @@ #include -PHP_HTTP_API php_http_request_t *php_http_request_init(php_http_request_t *h, php_http_request_ops_t *ops, void *init_arg TSRMLS_DC) +PHP_HTTP_API php_http_request_t *php_http_request_init(php_http_request_t *h, php_http_request_ops_t *ops, php_http_resource_factory_t *rf, void *init_arg TSRMLS_DC) { php_http_request_t *free_h = NULL; @@ -29,6 +29,7 @@ PHP_HTTP_API php_http_request_t *php_http_request_init(php_http_request_t *h, ph memset(h, 0, sizeof(*h)); h->ops = ops; + h->rf = rf ? rf : php_http_resource_factory_init(NULL, h->ops->rsrc, NULL, NULL TSRMLS_CC); h->buffer = php_http_buffer_init(NULL TSRMLS_CC); h->parser = php_http_message_parser_init(NULL TSRMLS_CC); h->message = php_http_message_init(NULL, 0 TSRMLS_CC); @@ -53,6 +54,12 @@ PHP_HTTP_API void php_http_request_dtor(php_http_request_t *h) h->ops->dtor(h); } + php_http_resource_factory_free(&h->rf); + + if (h->persistent_handle_id) { + zval_ptr_dtor(&h->persistent_handle_id); + } + php_http_message_parser_free(&h->parser); php_http_message_free(&h->message); php_http_buffer_free(&h->buffer); @@ -306,7 +313,7 @@ zend_object_value php_http_request_object_new_ex(zend_class_entry *ce, php_http_ object_properties_init((zend_object *) o, ce); if (!(o->request = r)) { - o->request = php_http_request_init(NULL, NULL, NULL TSRMLS_CC); + o->request = php_http_request_init(NULL, NULL, NULL, NULL TSRMLS_CC); } if (ptr) { @@ -439,19 +446,19 @@ STATUS php_http_request_object_requesthandler(php_http_request_object_t *obj, zv if (SUCCESS == php_http_request_getopt(obj->request, PHP_HTTP_REQUEST_OPT_PROGRESS_INFO, &progress)) { if (!progress->callback) { - zval *pcb; - int no = 0; + php_http_request_progress_callback_t *callback = emalloc(sizeof(*callback)); - MAKE_STD_ZVAL(pcb); - array_init(pcb); + callback->type = PHP_HTTP_REQUEST_PROGRESS_CALLBACK_USER; + callback->pass_state = 0; + MAKE_STD_ZVAL(callback->func.user); + array_init(callback->func.user); Z_ADDREF_P(getThis()); - add_next_index_zval(pcb, getThis()); - add_next_index_stringl(pcb, ZEND_STRL("notify"), 1); + add_next_index_zval(callback->func.user, getThis()); + add_next_index_stringl(callback->func.user, ZEND_STRL("notify"), 1); - php_http_request_setopt(obj->request, PHP_HTTP_REQUEST_OPT_PROGRESS_CALLBACK, pcb); - php_http_request_setopt(obj->request, PHP_HTTP_REQUEST_OPT_PROGRESS_CALLBACK_WANTS_STATE, &no); - zval_ptr_dtor(&pcb); + php_http_request_setopt(obj->request, PHP_HTTP_REQUEST_OPT_PROGRESS_CALLBACK, callback); } + progress->state.info = "start"; php_http_request_progress_notify(progress TSRMLS_CC); progress->state.started = 1; } @@ -523,6 +530,7 @@ STATUS php_http_request_object_responsehandler(php_http_request_object_t *obj, z } if (SUCCESS == php_http_request_getopt(obj->request, PHP_HTTP_REQUEST_OPT_PROGRESS_INFO, &progress)) { + progress->state.info = "finished"; progress->state.finished = 1; php_http_request_progress_notify(progress TSRMLS_CC); } @@ -595,14 +603,14 @@ static inline void php_http_request_object_get_options_subr(INTERNAL_FUNCTION_PA PHP_METHOD(HttpRequest, __construct) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { zend_parse_parameters_none(); } end_error_handling(); } PHP_METHOD(HttpRequest, getObservers) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { if (SUCCESS == zend_parse_parameters_none()) { RETVAL_PROP(php_http_request_class_entry, "observers"); } @@ -675,6 +683,7 @@ PHP_METHOD(HttpRequest, getProgress) object_init(return_value); add_property_bool(return_value, "started", progress->state.started); add_property_bool(return_value, "finished", progress->state.finished); + add_property_string(return_value, "info", STR_PTR(progress->state.info), 1); add_property_double(return_value, "dltotal", progress->state.dl.total); add_property_double(return_value, "dlnow", progress->state.dl.now); add_property_double(return_value, "ultotal", progress->state.ul.total); @@ -965,7 +974,7 @@ PHP_METHOD(HttpRequest, setQueryData) efree(query_data_str); } } else { - zval *data = php_http_zsep(IS_STRING, qdata); + zval *data = php_http_ztyp(IS_STRING, qdata); zend_update_property_stringl(php_http_request_class_entry, getThis(), ZEND_STRL("queryData"), Z_STRVAL_P(data), Z_STRLEN_P(data) TSRMLS_CC); zval_ptr_dtor(&data); @@ -1087,7 +1096,7 @@ PHP_METHOD(HttpRequest, getResponseCookies) if (allowed_extras_array) { allowed_extras = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array)) + 1, sizeof(char *)); FOREACH_VAL(pos, allowed_extras_array, entry) { - zval *data = php_http_zsep(IS_STRING, *entry); + zval *data = php_http_ztyp(IS_STRING, *entry); allowed_extras[i++] = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data)); zval_ptr_dtor(&data); } @@ -1101,7 +1110,7 @@ PHP_METHOD(HttpRequest, getResponseCookies) zval **single_header; FOREACH_VAL(pos2, *header, single_header) { - zval *data = php_http_zsep(IS_STRING, *single_header); + zval *data = php_http_ztyp(IS_STRING, *single_header); if ((list = php_http_cookie_list_parse(NULL, Z_STRVAL_P(data), flags, allowed_extras TSRMLS_CC))) { zval *cookie; @@ -1113,7 +1122,7 @@ PHP_METHOD(HttpRequest, getResponseCookies) zval_ptr_dtor(&data); } } else { - zval *data = php_http_zsep(IS_STRING, *header); + zval *data = php_http_ztyp(IS_STRING, *header); if ((list = php_http_cookie_list_parse(NULL, Z_STRVAL_P(data), flags, allowed_extras TSRMLS_CC))) { zval *cookie; @@ -1167,7 +1176,7 @@ PHP_METHOD(HttpRequest, getResponseStatus) PHP_METHOD(HttpRequest, getResponseMessage) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { if (SUCCESS == zend_parse_parameters_none()) { zval *message = zend_read_property(php_http_request_class_entry, getThis(), ZEND_STRL("responseMessage"), 0 TSRMLS_CC); @@ -1182,7 +1191,7 @@ PHP_METHOD(HttpRequest, getResponseMessage) PHP_METHOD(HttpRequest, getRequestMessage) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { if (SUCCESS == zend_parse_parameters_none()) { zval *message = zend_read_property(php_http_request_class_entry, getThis(), ZEND_STRL("requestMessage"), 0 TSRMLS_CC); @@ -1197,7 +1206,7 @@ PHP_METHOD(HttpRequest, getRequestMessage) PHP_METHOD(HttpRequest, getHistory) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { if (SUCCESS == zend_parse_parameters_none()) { zval *hist = zend_read_property(php_http_request_class_entry, getThis(), ZEND_STRL("history"), 0 TSRMLS_CC); @@ -1241,7 +1250,7 @@ PHP_METHOD(HttpRequest, send) { RETVAL_FALSE; - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { if (SUCCESS == zend_parse_parameters_none()) { php_http_request_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); php_http_request_method_t meth = PHP_HTTP_NO_REQUEST_METHOD; diff --git a/php_http_request.h b/php_http_request.h index b848612..96baa36 100644 --- a/php_http_request.h +++ b/php_http_request.h @@ -28,17 +28,39 @@ typedef struct php_http_request_progress_state { double now; double total; } dl; + const char *info; unsigned started:1; unsigned finished:1; } php_http_request_progress_state_t; +#define PHP_HTTP_REQUEST_PROGRESS_CALLBACK_USER 0 +#define PHP_HTTP_REQUEST_PROGRESS_CALLBACK_INTERN 1 +typedef struct php_http_request_progress_callback { + union { + zval *user; + void (*intern)(php_http_request_progress_state_t* TSRMLS_DC); + } func; + unsigned type:1; + unsigned pass_state:1; +} php_http_request_progress_callback_t; + typedef struct php_http_request_progress { php_http_request_progress_state_t state; - zval *callback; + php_http_request_progress_callback_t *callback; unsigned in_cb:1; - unsigned pass_state:1; } php_http_request_progress_t; +static inline void php_http_request_progress_dtor(php_http_request_progress_t *progress TSRMLS_DC) +{ + if (progress->callback) { + if (progress->callback->type == PHP_HTTP_REQUEST_PROGRESS_CALLBACK_USER) { + zval_ptr_dtor(&progress->callback->func.user); + } + efree(progress->callback); + } + memset(progress, 0, sizeof(*progress)); +} + static inline void php_http_request_progress_notify(php_http_request_progress_t *progress TSRMLS_DC) { if (progress->callback) { @@ -48,27 +70,37 @@ static inline void php_http_request_progress_notify(php_http_request_progress_t ZVAL_NULL(&retval); with_error_handling(EH_NORMAL, NULL) { - if (progress->pass_state) { - zval *param; - - MAKE_STD_ZVAL(param); - array_init(param); - add_assoc_bool(param, "started", progress->state.started); - add_assoc_bool(param, "finished", progress->state.finished); - add_assoc_double(param, "dltotal", progress->state.dl.total); - add_assoc_double(param, "dlnow", progress->state.dl.now); - add_assoc_double(param, "ultotal", progress->state.ul.total); - add_assoc_double(param, "ulnow", progress->state.ul.now); - - progress->in_cb = 1; - call_user_function(EG(function_table), NULL, progress->callback, &retval, 1, ¶m TSRMLS_CC); - progress->in_cb = 0; - - zval_ptr_dtor(¶m); - } else { - progress->in_cb = 1; - call_user_function(EG(function_table), NULL, progress->callback, &retval, 0, NULL TSRMLS_CC); - progress->in_cb = 0; + switch (progress->callback->type) { + case PHP_HTTP_REQUEST_PROGRESS_CALLBACK_USER: + if (progress->callback->pass_state) { + zval *param; + + MAKE_STD_ZVAL(param); + array_init(param); + add_assoc_bool(param, "started", progress->state.started); + add_assoc_bool(param, "finished", progress->state.finished); + add_assoc_string(param, "info", estrdup(progress->state.info), 0); + add_assoc_double(param, "dltotal", progress->state.dl.total); + add_assoc_double(param, "dlnow", progress->state.dl.now); + add_assoc_double(param, "ultotal", progress->state.ul.total); + add_assoc_double(param, "ulnow", progress->state.ul.now); + + progress->in_cb = 1; + call_user_function(EG(function_table), NULL, progress->callback->func.user, &retval, 1, ¶m TSRMLS_CC); + progress->in_cb = 0; + + zval_ptr_dtor(¶m); + } else { + progress->in_cb = 1; + call_user_function(EG(function_table), NULL, progress->callback->func.user, &retval, 0, NULL TSRMLS_CC); + progress->in_cb = 0; + } + break; + case PHP_HTTP_REQUEST_PROGRESS_CALLBACK_INTERN: + progress->callback->func.intern(progress->callback->pass_state ? &progress->state : NULL TSRMLS_CC); + break; + default: + break; } } end_error_handling(); @@ -78,8 +110,7 @@ static inline void php_http_request_progress_notify(php_http_request_progress_t typedef enum php_http_request_setopt_opt { PHP_HTTP_REQUEST_OPT_SETTINGS, /* HashTable* */ - PHP_HTTP_REQUEST_OPT_PROGRESS_CALLBACK, /* zval* */ - PHP_HTTP_REQUEST_OPT_PROGRESS_CALLBACK_WANTS_STATE, /* int* */ + PHP_HTTP_REQUEST_OPT_PROGRESS_CALLBACK, /* php_http_request_progress_callback_t* */ PHP_HTTP_REQUEST_OPT_COOKIES_ENABLE, /* - */ PHP_HTTP_REQUEST_OPT_COOKIES_RESET, /* - */ PHP_HTTP_REQUEST_OPT_COOKIES_RESET_SESSION, /* - */ @@ -102,6 +133,7 @@ typedef STATUS (*php_http_request_setopt_func_t)(php_http_request_t *h, php_http typedef STATUS (*php_http_request_getopt_func_t)(php_http_request_t *h, php_http_request_getopt_opt_t opt, void *arg); typedef struct php_http_request_ops { + php_http_resource_factory_ops_t *rsrc; php_http_request_init_func_t init; php_http_request_copy_func_t copy; php_http_request_dtor_func_t dtor; @@ -115,16 +147,18 @@ PHP_HTTP_API php_http_request_ops_t *php_http_request_get_default_ops(TSRMLS_D); struct php_http_request { void *ctx; + php_http_resource_factory_t *rf; php_http_request_ops_t *ops; php_http_message_parser_t *parser; php_http_message_t *message; php_http_buffer_t *buffer; + zval *persistent_handle_id; #ifdef ZTS void ***ts; #endif }; -PHP_HTTP_API php_http_request_t *php_http_request_init(php_http_request_t *h, php_http_request_ops_t *ops, void *init_arg TSRMLS_DC); +PHP_HTTP_API php_http_request_t *php_http_request_init(php_http_request_t *h, php_http_request_ops_t *ops, php_http_resource_factory_t *rf, void *init_arg TSRMLS_DC); PHP_HTTP_API php_http_request_t *php_http_request_copy(php_http_request_t *from, php_http_request_t *to); PHP_HTTP_API STATUS php_http_request_exec(php_http_request_t *h, php_http_request_method_t meth, const char *url, php_http_message_body_t *body); PHP_HTTP_API STATUS php_http_request_reset(php_http_request_t *h); diff --git a/php_http_request_datashare.c b/php_http_request_datashare.c index 68e4c07..f44d5b0 100644 --- a/php_http_request_datashare.c +++ b/php_http_request_datashare.c @@ -28,7 +28,7 @@ php_http_request_datashare_t *php_http_request_datashare_global_get(const char * php_http_request_factory_driver_t driver; if ((SUCCESS == php_http_request_factory_get_driver(driver_str, driver_len, &driver)) && driver.request_datashare_ops) { - s = php_http_request_datashare_init(NULL, driver.request_datashare_ops, NULL, 1 TSRMLS_CC); + s = php_http_request_datashare_init(NULL, driver.request_datashare_ops, NULL, NULL, 1 TSRMLS_CC); zend_hash_add(&php_http_request_datashare_global_shares, lower_str, driver_len + 1, &s, sizeof(php_http_request_datashare_t *), NULL); } } @@ -40,9 +40,9 @@ php_http_request_datashare_t *php_http_request_datashare_global_get(const char * return s; } -PHP_HTTP_API php_http_request_datashare_t *php_http_request_datashare_init(php_http_request_datashare_t *h, php_http_request_datashare_ops_t *ops, void *init_arg, zend_bool persistent TSRMLS_DC) +PHP_HTTP_API php_http_request_datashare_t *php_http_request_datashare_init(php_http_request_datashare_t *h, php_http_request_datashare_ops_t *ops, php_http_resource_factory_t *rf, void *init_arg, zend_bool persistent TSRMLS_DC) { - php_http_request_datashare_t *free_h; + php_http_request_datashare_t *free_h = NULL; if (!h) { free_h = h = pemalloc(sizeof(*h), persistent); @@ -55,6 +55,7 @@ PHP_HTTP_API php_http_request_datashare_t *php_http_request_datashare_init(php_h TSRMLS_SET_CTX(h->ts); } h->ops = ops; + h->rf = rf ? rf : php_http_resource_factory_init(NULL, h->ops->rsrc, NULL, NULL TSRMLS_CC); if (h->ops->init) { if (!(h = h->ops->init(h, init_arg))) { @@ -86,6 +87,10 @@ PHP_HTTP_API void php_http_request_datashare_dtor(php_http_request_datashare_t * pefree(h->requests, h->persistent); h->requests = NULL; } + + if (h->persistent_handle_id) { + zval_ptr_dtor(&h->persistent_handle_id); + } } PHP_HTTP_API void php_http_request_datashare_free(php_http_request_datashare_t **h) @@ -212,7 +217,7 @@ zend_object_value php_http_request_datashare_object_new_ex(zend_class_entry *ce, if (share) { o->share = share; } else { - o->share = php_http_request_datashare_init(NULL, NULL, NULL, 0 TSRMLS_CC); + o->share = php_http_request_datashare_init(NULL, NULL, NULL, NULL, 0 TSRMLS_CC); } if (ptr) { @@ -275,7 +280,7 @@ static zval **php_http_request_datashare_object_get_prop_ptr(zval *object, zval PHP_METHOD(HttpRequestDataShare, __construct) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { zend_parse_parameters_none(); } end_error_handling(); } diff --git a/php_http_request_datashare.h b/php_http_request_datashare.h index cdc4142..3b71962 100644 --- a/php_http_request_datashare.h +++ b/php_http_request_datashare.h @@ -19,6 +19,7 @@ typedef STATUS (*php_http_request_datashare_detach_func_t)(php_http_request_data typedef STATUS (*php_http_request_datashare_setopt_func_t)(php_http_request_datashare_t *h, php_http_request_datashare_setopt_opt_t opt, void *arg); typedef struct php_http_request_datashare_ops { + php_http_resource_factory_ops_t *rsrc; php_http_request_datashare_init_func_t init; php_http_request_datashare_copy_func_t copy; php_http_request_datashare_dtor_func_t dtor; @@ -31,9 +32,11 @@ typedef struct php_http_request_datashare_ops { #define PHP_HTTP_REQUEST_DATASHARE_REQUESTS(s) ((s)->persistent ? &PHP_HTTP_G->request_datashare.requests : (s)->requests) struct php_http_request_datashare { void *ctx; + php_http_resource_factory_t *rf; php_http_request_datashare_ops_t *ops; zend_llist *requests; /* NULL if persistent, use PHP_HTTP_REQUEST_DATASHARE_REQUESTS */ unsigned persistent:1; + zval *persistent_handle_id; #ifdef ZTS void ***ts; #endif @@ -54,7 +57,7 @@ extern PHP_MSHUTDOWN_FUNCTION(http_request_datashare); extern PHP_RINIT_FUNCTION(http_request_datashare); extern PHP_RSHUTDOWN_FUNCTION(http_request_datashare); -PHP_HTTP_API php_http_request_datashare_t *php_http_request_datashare_init(php_http_request_datashare_t *h, php_http_request_datashare_ops_t *ops, void *init_arg, zend_bool persistent TSRMLS_DC); +PHP_HTTP_API php_http_request_datashare_t *php_http_request_datashare_init(php_http_request_datashare_t *h, php_http_request_datashare_ops_t *ops, php_http_resource_factory_t *rf, void *init_arg, zend_bool persistent TSRMLS_DC); PHP_HTTP_API php_http_request_datashare_t *php_http_request_datashare_copy(php_http_request_datashare_t *from, php_http_request_datashare_t *to); PHP_HTTP_API void php_http_request_datashare_dtor(php_http_request_datashare_t *h); PHP_HTTP_API void php_http_request_datashare_free(php_http_request_datashare_t **h); diff --git a/php_http_request_factory.c b/php_http_request_factory.c index 16352ee..a4ac4f0 100644 --- a/php_http_request_factory.c +++ b/php_http_request_factory.c @@ -47,7 +47,6 @@ static zend_class_entry *php_http_request_factory_get_class_entry(zval *this_ptr #define PHP_HTTP_REQUEST_FACTORY_MALIAS(me, al, vis) ZEND_FENTRY(me, ZEND_MN(HttpRequestFactory_##al), PHP_HTTP_ARGS(HttpRequestFactory, al), vis) PHP_HTTP_BEGIN_ARGS(__construct, 1) - PHP_HTTP_ARG_VAL(driver, 0) PHP_HTTP_ARG_VAL(options, 0) PHP_HTTP_END_ARGS; PHP_HTTP_BEGIN_ARGS(createRequest, 0) @@ -78,34 +77,23 @@ zend_function_entry php_http_request_factory_method_entry[] = { PHP_METHOD(HttpRequestFactory, __construct) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { - char *driver_str; - int driver_len; + with_error_handling(EH_THROW, php_http_exception_class_entry) { HashTable *options = NULL; - if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|h", &driver_str, &driver_len, &options)) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(request_factory)) { - char *lower_str = php_strtolower(estrdup(driver_str), driver_len); - - if (zend_hash_exists(&php_http_request_factory_drivers, lower_str, driver_len + 1)) { - zend_update_property_stringl(php_http_request_factory_class_entry, getThis(), ZEND_STRL("driver"), lower_str, driver_len TSRMLS_CC); - - if (options) { - zval **val; - HashPosition pos; - php_http_array_hashkey_t key = php_http_array_hashkey_init(0); - - FOREACH_HASH_KEYVAL(pos, options, key, val) { - if (key.type == HASH_KEY_IS_STRING) { - zend_update_property(php_http_request_factory_class_entry, getThis(), key.str, key.len - 1, *val); - } - } + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|h", &options)) { + if (options) { + zval **val; + HashPosition pos; + php_http_array_hashkey_t key = php_http_array_hashkey_init(0); + + FOREACH_HASH_KEYVAL(pos, options, key, val) { + if (key.type == HASH_KEY_IS_STRING) { + zval *newval = php_http_zsep(1, Z_TYPE_PP(val), *val); + zend_update_property(php_http_request_factory_class_entry, getThis(), key.str, key.len - 1, newval); + zval_ptr_dtor(&newval); } - } else { - php_http_error(HE_THROW, PHP_HTTP_E_REQUEST_FACTORY, "unknown request driver: '%s'", driver_str); } - efree(lower_str); - } end_error_handling(); + } } } end_error_handling(); } @@ -117,48 +105,74 @@ PHP_METHOD(HttpRequestFactory, createRequest) long meth = -1; zval *options = NULL; - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!la!", &url_str, &url_len, &meth, &options)) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(request_factory)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { zval *zdriver, *os; zend_object_value ov; zend_class_entry *class_entry = NULL; php_http_request_t *req = NULL; php_http_request_factory_driver_t driver; - if (!(class_entry = php_http_request_factory_get_class_entry(getThis(), ZEND_STRL("requestClass") TSRMLS_CC))) { + class_entry = php_http_request_factory_get_class_entry(getThis(), ZEND_STRL("requestClass") TSRMLS_CC); + + if (!class_entry) { class_entry = php_http_request_class_entry; } - if ((zdriver = zend_read_property(php_http_request_factory_class_entry, getThis(), ZEND_STRL("driver"), 0 TSRMLS_CC)) - && (IS_STRING == Z_TYPE_P(zdriver)) - && (SUCCESS == php_http_request_factory_get_driver(Z_STRVAL_P(zdriver), Z_STRLEN_P(zdriver), &driver)) - && (driver.request_ops) - && (req = php_http_request_init(NULL, driver.request_ops, NULL TSRMLS_CC)) - && (SUCCESS == php_http_new(&ov, class_entry, (php_http_new_t) php_http_request_object_new_ex, php_http_request_class_entry, req, NULL TSRMLS_CC)) - ) { - ZVAL_OBJVAL(return_value, ov, 0); - - MAKE_STD_ZVAL(os); - object_init_ex(os, spl_ce_SplObjectStorage); - zend_update_property(php_http_request_class_entry, return_value, ZEND_STRL("observers"), os TSRMLS_CC); - zval_ptr_dtor(&os); - - if (url_str) { - zend_update_property_stringl(php_http_request_class_entry, return_value, ZEND_STRL("url"), url_str, url_len TSRMLS_CC); - } - if (meth > 0) { - zend_update_property_long(php_http_request_class_entry, return_value, ZEND_STRL("method"), meth TSRMLS_CC); - } - if (options) { - zend_call_method_with_1_params(&return_value, Z_OBJCE_P(return_value), NULL, "setoptions", NULL, options); + zdriver = zend_read_property(php_http_request_factory_class_entry, getThis(), ZEND_STRL("driver"), 0 TSRMLS_CC); + + if ((IS_STRING == Z_TYPE_P(zdriver)) && (SUCCESS == php_http_request_factory_get_driver(Z_STRVAL_P(zdriver), Z_STRLEN_P(zdriver), &driver)) && driver.request_ops) { + zval *phi = php_http_zsep(1, IS_STRING, zend_read_property(php_http_request_factory_class_entry, getThis(), ZEND_STRL("persistentHandleId"), 0 TSRMLS_CC)); + php_http_resource_factory_t *rf = NULL; + + if (Z_STRLEN_P(phi)) { + char *name_str; + size_t name_len; + php_http_persistent_handle_factory_t *pf; + + name_len = spprintf(&name_str, 0, "http_request.%s", Z_STRVAL_P(zdriver)); + + if ((pf = php_http_persistent_handle_concede(NULL , name_str, name_len, Z_STRVAL_P(phi), Z_STRLEN_P(phi) TSRMLS_CC))) { + php_http_resource_factory_ops_t ops = { + php_http_persistent_handle_acquire, + php_http_persistent_handle_accrete, + php_http_persistent_handle_release + }; + + rf = php_http_resource_factory_init(NULL, &ops, pf, php_http_persistent_handle_abandon TSRMLS_CC); + } + + efree(name_str); } - } else { + + req = php_http_request_init(NULL, driver.request_ops, rf, NULL TSRMLS_CC); if (req) { - php_http_request_free(&req); - } else { - php_http_error(HE_WARNING, PHP_HTTP_E_REQUEST_FACTORY, "requests are not supported by this driver"); + if (SUCCESS == php_http_new(&ov, class_entry, (php_http_new_t) php_http_request_object_new_ex, php_http_request_class_entry, req, NULL TSRMLS_CC)) { + ZVAL_OBJVAL(return_value, ov, 0); + + MAKE_STD_ZVAL(os); + object_init_ex(os, spl_ce_SplObjectStorage); + zend_update_property(php_http_request_class_entry, return_value, ZEND_STRL("observers"), os TSRMLS_CC); + zval_ptr_dtor(&os); + + if (url_str) { + zend_update_property_stringl(php_http_request_class_entry, return_value, ZEND_STRL("url"), url_str, url_len TSRMLS_CC); + } + if (meth > 0) { + zend_update_property_long(php_http_request_class_entry, return_value, ZEND_STRL("method"), meth TSRMLS_CC); + } + if (options) { + zend_call_method_with_1_params(&return_value, Z_OBJCE_P(return_value), NULL, "setoptions", NULL, options); + } + } else { + php_http_request_free(&req); + } } + + zval_ptr_dtor(&phi); + } else { + php_http_error(HE_WARNING, PHP_HTTP_E_REQUEST_FACTORY, "requests are not supported by this driver"); } } end_error_handling(); } @@ -170,41 +184,62 @@ PHP_METHOD(HttpRequestFactory, createPool) int argc = 0; zval ***argv; - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|*", &argv, &argc)) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(request_factory)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { int i; zval *zdriver; zend_object_value ov; zend_class_entry *class_entry = NULL; php_http_request_pool_t *pool = NULL; - php_http_request_pool_object_t *obj; php_http_request_factory_driver_t driver; if (!(class_entry = php_http_request_factory_get_class_entry(getThis(), ZEND_STRL("requestPoolClass") TSRMLS_CC))) { class_entry = php_http_request_pool_class_entry; } - if ((zdriver = zend_read_property(php_http_request_factory_class_entry, getThis(), ZEND_STRL("driver"), 0 TSRMLS_CC)) - && (IS_STRING == Z_TYPE_P(zdriver)) - && (SUCCESS == php_http_request_factory_get_driver(Z_STRVAL_P(zdriver), Z_STRLEN_P(zdriver), &driver)) - && (driver.request_pool_ops) - && (pool = php_http_request_pool_init(NULL, driver.request_pool_ops, NULL TSRMLS_CC)) - && (SUCCESS == php_http_new(&ov, class_entry, (php_http_new_t) php_http_request_pool_object_new_ex, php_http_request_pool_class_entry, pool, (void *) &obj TSRMLS_CC)) - ) { - ZVAL_OBJVAL(return_value, ov, 0); - - for (i = 0; i < argc; ++i) { - if (Z_TYPE_PP(argv[i]) == IS_OBJECT && instanceof_function(Z_OBJCE_PP(argv[i]), php_http_request_class_entry TSRMLS_CC)) { - php_http_request_pool_attach(obj->pool, *(argv[i])); + zdriver = zend_read_property(php_http_request_factory_class_entry, getThis(), ZEND_STRL("driver"), 0 TSRMLS_CC); + if ((IS_STRING == Z_TYPE_P(zdriver)) && (SUCCESS == php_http_request_factory_get_driver(Z_STRVAL_P(zdriver), Z_STRLEN_P(zdriver), &driver)) && driver.request_pool_ops) { + zval *phi = php_http_zsep(1, IS_STRING, zend_read_property(php_http_request_factory_class_entry, getThis(), ZEND_STRL("persistentHandleId"), 0 TSRMLS_CC)); + php_http_resource_factory_t *rf = NULL; + + if (Z_STRLEN_P(phi)) { + char *name_str; + size_t name_len; + php_http_persistent_handle_factory_t *pf; + + name_len = spprintf(&name_str, 0, "http_request_pool.%s", Z_STRVAL_P(zdriver)); + + if ((pf = php_http_persistent_handle_concede(NULL , name_str, name_len, Z_STRVAL_P(phi), Z_STRLEN_P(phi) TSRMLS_CC))) { + php_http_resource_factory_ops_t ops = { + php_http_persistent_handle_acquire, + php_http_persistent_handle_accrete, + php_http_persistent_handle_release + }; + + rf = php_http_resource_factory_init(NULL, &ops, pf, php_http_persistent_handle_abandon TSRMLS_CC); } + + efree(name_str); } - } else { + + pool = php_http_request_pool_init(NULL, driver.request_pool_ops, rf, NULL TSRMLS_CC); if (pool) { - php_http_request_pool_free(&pool); - } else { - php_http_error(HE_WARNING, PHP_HTTP_E_REQUEST_FACTORY, "pools are not supported by this driver"); + if (SUCCESS == php_http_new(&ov, class_entry, (php_http_new_t) php_http_request_pool_object_new_ex, php_http_request_pool_class_entry, pool, NULL TSRMLS_CC)) { + ZVAL_OBJVAL(return_value, ov, 0); + for (i = 0; i < argc; ++i) { + if (Z_TYPE_PP(argv[i]) == IS_OBJECT && instanceof_function(Z_OBJCE_PP(argv[i]), php_http_request_class_entry TSRMLS_CC)) { + php_http_request_pool_attach(pool, *(argv[i])); + } + } + } else { + php_http_request_pool_free(&pool); + } } + + zval_ptr_dtor(&phi); + } else { + php_http_error(HE_WARNING, PHP_HTTP_E_REQUEST_FACTORY, "pools are not supported by this driver"); } } end_error_handling(); } @@ -216,41 +251,62 @@ PHP_METHOD(HttpRequestFactory, createDataShare) int argc = 0; zval ***argv; - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|*", &argv, &argc)) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(request_factory)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { int i; zval *zdriver; zend_object_value ov; zend_class_entry *class_entry; php_http_request_datashare_t *share = NULL; - php_http_request_datashare_object_t *obj; php_http_request_factory_driver_t driver; if (!(class_entry = php_http_request_factory_get_class_entry(getThis(), ZEND_STRL("requestDataShareClass") TSRMLS_CC))) { class_entry = php_http_request_datashare_class_entry; } - if ((zdriver = zend_read_property(php_http_request_factory_class_entry, getThis(), ZEND_STRL("driver"), 0 TSRMLS_CC)) - && (IS_STRING == Z_TYPE_P(zdriver)) - && (SUCCESS == php_http_request_factory_get_driver(Z_STRVAL_P(zdriver), Z_STRLEN_P(zdriver), &driver)) - && (driver.request_datashare_ops) - && (share = php_http_request_datashare_init(NULL, driver.request_datashare_ops, NULL, 0 TSRMLS_CC)) - && (SUCCESS == php_http_new(&ov, class_entry, (php_http_new_t) php_http_request_datashare_object_new_ex, php_http_request_datashare_class_entry, share, (void *) &obj TSRMLS_CC)) - ) { - ZVAL_OBJVAL(return_value, ov, 0); - - for (i = 0; i < argc; ++i) { - if (Z_TYPE_PP(argv[i]) == IS_OBJECT && instanceof_function(Z_OBJCE_PP(argv[i]), php_http_request_class_entry TSRMLS_CC)) { - php_http_request_datashare_attach(obj->share, *(argv[i])); + zdriver = zend_read_property(php_http_request_factory_class_entry, getThis(), ZEND_STRL("driver"), 0 TSRMLS_CC); + if ((IS_STRING == Z_TYPE_P(zdriver)) && (SUCCESS == php_http_request_factory_get_driver(Z_STRVAL_P(zdriver), Z_STRLEN_P(zdriver), &driver)) && driver.request_datashare_ops) { + zval *phi = php_http_zsep(1, IS_STRING, zend_read_property(php_http_request_factory_class_entry, getThis(), ZEND_STRL("persistentHandleId"), 0 TSRMLS_CC)); + php_http_resource_factory_t *rf = NULL; + + if (Z_STRLEN_P(phi)) { + char *name_str; + size_t name_len; + php_http_persistent_handle_factory_t *pf; + + name_len = spprintf(&name_str, 0, "http_request_datashare.%s", Z_STRVAL_P(zdriver)); + + if ((pf = php_http_persistent_handle_concede(NULL , name_str, name_len, Z_STRVAL_P(phi), Z_STRLEN_P(phi) TSRMLS_CC))) { + php_http_resource_factory_ops_t ops = { + php_http_persistent_handle_acquire, + php_http_persistent_handle_accrete, + php_http_persistent_handle_release + }; + + rf = php_http_resource_factory_init(NULL, &ops, pf, php_http_persistent_handle_abandon TSRMLS_CC); } + + efree(name_str); } - } else { + + share = php_http_request_datashare_init(NULL, driver.request_datashare_ops, rf, NULL, 0 TSRMLS_CC); if (share) { - php_http_request_datashare_free(&share); - } else { - php_http_error(HE_WARNING, PHP_HTTP_E_REQUEST_FACTORY, "datashares are not supported by this driver"); + if (SUCCESS == php_http_new(&ov, class_entry, (php_http_new_t) php_http_request_datashare_object_new_ex, php_http_request_datashare_class_entry, share, NULL TSRMLS_CC)) { + ZVAL_OBJVAL(return_value, ov, 0); + for (i = 0; i < argc; ++i) { + if (Z_TYPE_PP(argv[i]) == IS_OBJECT && instanceof_function(Z_OBJCE_PP(argv[i]), php_http_request_class_entry TSRMLS_CC)) { + php_http_request_datashare_attach(share, *(argv[i])); + } + } + } else { + php_http_request_datashare_free(&share); + } } + + zval_ptr_dtor(&phi); + } else { + php_http_error(HE_WARNING, PHP_HTTP_E_REQUEST_FACTORY, "datashares are not supported by this driver"); } } end_error_handling(); } @@ -259,9 +315,9 @@ PHP_METHOD(HttpRequestFactory, createDataShare) PHP_METHOD(HttpRequestFactory, getGlobalDataShareInstance) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { if (SUCCESS == zend_parse_parameters_none()) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(request_datashare)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { zval *instance = *zend_std_get_static_property(php_http_request_datashare_class_entry, ZEND_STRL("instance"), 0, NULL TSRMLS_CC); if (Z_TYPE_P(instance) != IS_OBJECT) { @@ -327,10 +383,13 @@ PHP_MINIT_FUNCTION(http_request_factory) zend_hash_init(&php_http_request_factory_drivers, 0, NULL, NULL, 1); PHP_HTTP_REGISTER_CLASS(http\\request, Factory, http_request_factory, php_http_object_class_entry, 0); - zend_declare_property_null(php_http_request_factory_class_entry, ZEND_STRL("driver"), ZEND_ACC_PRIVATE TSRMLS_CC); - zend_declare_property_null(php_http_request_factory_class_entry, ZEND_STRL("requestClass"), ZEND_ACC_PUBLIC TSRMLS_CC); - zend_declare_property_null(php_http_request_factory_class_entry, ZEND_STRL("requestPoolClass"), ZEND_ACC_PUBLIC TSRMLS_CC); - zend_declare_property_null(php_http_request_factory_class_entry, ZEND_STRL("requestDataShareClass"), ZEND_ACC_PUBLIC TSRMLS_CC); + php_http_request_factory_class_entry->create_object = php_http_request_factory_new; + + zend_declare_property_stringl(php_http_request_factory_class_entry, ZEND_STRL("driver"), ZEND_STRL("curl"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(php_http_request_factory_class_entry, ZEND_STRL("persistentHandleId"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(php_http_request_factory_class_entry, ZEND_STRL("requestClass"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(php_http_request_factory_class_entry, ZEND_STRL("requestPoolClass"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(php_http_request_factory_class_entry, ZEND_STRL("requestDataShareClass"), ZEND_ACC_PROTECTED TSRMLS_CC); return SUCCESS; } diff --git a/php_http_request_pool.c b/php_http_request_pool.c index 7f081b8..379e3b1 100644 --- a/php_http_request_pool.c +++ b/php_http_request_pool.c @@ -4,7 +4,7 @@ #include #include -PHP_HTTP_API php_http_request_pool_t *php_http_request_pool_init(php_http_request_pool_t *h, php_http_request_pool_ops_t *ops, void *init_arg TSRMLS_DC) +PHP_HTTP_API php_http_request_pool_t *php_http_request_pool_init(php_http_request_pool_t *h, php_http_request_pool_ops_t *ops, php_http_resource_factory_t *rf, void *init_arg TSRMLS_DC) { php_http_request_pool_t *free_h = NULL; @@ -14,6 +14,7 @@ PHP_HTTP_API php_http_request_pool_t *php_http_request_pool_init(php_http_reques memset(h, 0, sizeof(*h)); h->ops = ops; + h->rf = rf ? rf : php_http_resource_factory_init(NULL, h->ops->rsrc, NULL, NULL TSRMLS_CC); zend_llist_init(&h->requests.attached, sizeof(zval *), (llist_dtor_func_t) ZVAL_PTR_DTOR, 0); zend_llist_init(&h->requests.finished, sizeof(zval *), (llist_dtor_func_t) ZVAL_PTR_DTOR, 0); TSRMLS_SET_CTX(h->ts); @@ -47,6 +48,10 @@ PHP_HTTP_API void php_http_request_pool_dtor(php_http_request_pool_t *h) zend_llist_clean(&h->requests.finished); zend_llist_clean(&h->requests.attached); + + if (h->persistent_handle_id) { + zval_ptr_dtor(&h->persistent_handle_id); + } } PHP_HTTP_API void php_http_request_pool_free(php_http_request_pool_t **h) { @@ -285,7 +290,7 @@ zend_object_value php_http_request_pool_object_new_ex(zend_class_entry *ce, php_ object_properties_init((zend_object *) o, ce); if (!(o->pool = p)) { - o->pool = php_http_request_pool_init(NULL, NULL, NULL TSRMLS_CC); + o->pool = php_http_request_pool_init(NULL, NULL, NULL, NULL TSRMLS_CC); } if (ptr) { @@ -316,7 +321,7 @@ static void php_http_request_pool_object_llist2array(zval **req, zval *array TSR PHP_METHOD(HttpRequestPool, __construct) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { zend_parse_parameters_none(); } end_error_handling(); } @@ -345,11 +350,11 @@ PHP_METHOD(HttpRequestPool, reset) PHP_METHOD(HttpRequestPool, attach) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { zval *request; if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, php_http_request_class_entry)) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { php_http_request_pool_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); if (obj->iterator.pos > 0 && obj->iterator.pos < zend_llist_count(&obj->pool->requests.attached)) { @@ -368,11 +373,11 @@ PHP_METHOD(HttpRequestPool, detach) { RETVAL_FALSE; - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { zval *request; if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, php_http_request_class_entry)) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(request_pool)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { php_http_request_pool_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); obj->iterator.pos = -1; @@ -388,9 +393,9 @@ PHP_METHOD(HttpRequestPool, send) { RETVAL_FALSE; - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { if (SUCCESS == zend_parse_parameters_none()) { - with_error_handling(EH_THROW, PHP_HTTP_EX_CE(request_pool)) { + with_error_handling(EH_THROW, php_http_exception_class_entry) { php_http_request_pool_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); php_http_request_pool_exec(obj->pool); diff --git a/php_http_request_pool.h b/php_http_request_pool.h index f75c01d..221292d 100644 --- a/php_http_request_pool.h +++ b/php_http_request_pool.h @@ -23,6 +23,7 @@ typedef STATUS (*php_http_request_pool_detach_func_t)(php_http_request_pool_t *p typedef STATUS (*php_http_request_pool_setopt_func_t)(php_http_request_pool_t *p, php_http_request_pool_setopt_opt_t opt, void *arg); typedef struct php_http_request_pool_ops { + php_http_resource_factory_ops_t *rsrc; php_http_request_pool_init_func_t init; php_http_request_pool_copy_func_t copy; php_http_request_pool_dtor_func_t dtor; @@ -37,6 +38,7 @@ typedef struct php_http_request_pool_ops { struct php_http_request_pool { void *ctx; + php_http_resource_factory_t *rf; php_http_request_pool_ops_t *ops; struct { @@ -44,12 +46,14 @@ struct php_http_request_pool { zend_llist finished; } requests; + zval *persistent_handle_id; + #ifdef ZTS void ***ts; #endif }; -PHP_HTTP_API php_http_request_pool_t *php_http_request_pool_init(php_http_request_pool_t *pool, php_http_request_pool_ops_t *ops, void *init_arg TSRMLS_DC); +PHP_HTTP_API php_http_request_pool_t *php_http_request_pool_init(php_http_request_pool_t *pool, php_http_request_pool_ops_t *ops, php_http_resource_factory_t *rf, void *init_arg TSRMLS_DC); PHP_HTTP_API php_http_request_pool_t *php_http_request_pool_copy(php_http_request_pool_t *from, php_http_request_pool_t *to); PHP_HTTP_API void php_http_request_pool_dtor(php_http_request_pool_t *pool); PHP_HTTP_API void php_http_request_pool_free(php_http_request_pool_t **pool); @@ -65,6 +69,7 @@ PHP_HTTP_API void php_http_request_pool_requests(php_http_request_pool_t *h, zva typedef struct php_http_request_pool_object { zend_object zo; php_http_request_pool_t *pool; + zend_object_value factory; struct { long pos; } iterator; -- 2.30.2