From: Michael Wallner Date: Tue, 7 Jun 2005 11:27:39 +0000 (+0000) Subject: - draft: implement curl_multi as HttpRequestPool X-Git-Tag: RELEASE_0_9_0~46 X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=commitdiff_plain;h=76a1064dde808801f4988df89521a323661742aa - draft: implement curl_multi as HttpRequestPool --- diff --git a/Makefile.frag b/Makefile.frag index e56cc68..773c9fa 100644 --- a/Makefile.frag +++ b/Makefile.frag @@ -17,6 +17,7 @@ HTTP_HEADER_FILES= \ php_http_auth_api.h \ php_http_exception_object.h \ php_http_request_object.h \ + php_http_requestpool_object.h \ php_http_url_api.h install-http-headers: diff --git a/config.m4 b/config.m4 index 58f290a..4f791d7 100644 --- a/config.m4 +++ b/config.m4 @@ -73,7 +73,7 @@ dnl DONE dnl ---- PHP_HTTP_SOURCES="missing.c http.c http_functions.c http_methods.c phpstr/phpstr.c \ http_util_object.c http_message_object.c http_request_object.c \ - http_response_object.c http_exception_object.c \ + http_response_object.c http_exception_object.c http_requestpool_object.c \ http_api.c http_auth_api.c http_cache_api.c http_request_api.c http_date_api.c \ http_headers_api.c http_message_api.c http_send_api.c http_url_api.c" PHP_NEW_EXTENSION([http], $PHP_HTTP_SOURCES, [$ext_shared]) diff --git a/config.w32 b/config.w32 index f539b40..a5a9b74 100644 --- a/config.w32 +++ b/config.w32 @@ -7,7 +7,7 @@ ARG_WITH("http-curl-zend-mm", "wheter ext/http's curl should use zend mm"); if (PHP_HTTP != "no") { EXTENSION("http", "missing.c http.c http_functions.c http_methods.c http_exception_object.c "+ - "http_util_object.c http_message_object.c "+ + "http_util_object.c http_message_object.c http_requestpool_object.c "+ "http_request_object.c http_response_object.c "+ "http_api.c http_auth_api.c http_cache_api.c "+ "http_request_api.c http_date_api.c http_headers_api.c "+ @@ -29,4 +29,4 @@ if (PHP_HTTP != "no") { } else { WARNING("curl convenience functions not enabled; libraries and headers not found"); } -} \ No newline at end of file +} diff --git a/http.c b/http.c index a09fa61..575fc3c 100644 --- a/http.c +++ b/http.c @@ -46,6 +46,7 @@ # include "php_http_response_object.h" # ifdef HTTP_HAVE_CURL # include "php_http_request_object.h" +# include "php_http_requestpool_object.h" # endif # include "php_http_exception_object.h" #endif @@ -184,6 +185,7 @@ static inline void http_globals_free(zend_http_globals *G) STR_FREE(G->send.content_type); STR_FREE(G->send.unquoted_etag); zend_hash_destroy(&G->request.methods.custom); + zend_llist_clean(&G->request.curl.copies); } /* }}} */ @@ -242,6 +244,7 @@ PHP_MINIT_FUNCTION(http) http_response_object_init(); # ifdef HTTP_HAVE_CURL http_request_object_init(); + http_requestpool_object_init(); # endif /* HTTP_HAVE_CURL */ http_exception_object_init(); #endif /* ZEND_ENGINE_2 */ diff --git a/http_methods.c b/http_methods.c index a8e0560..cf8f25d 100644 --- a/http_methods.c +++ b/http_methods.c @@ -36,6 +36,7 @@ #include "php_http_message_object.h" #include "php_http_response_object.h" #include "php_http_request_object.h" +#include "php_http_requestpool_object.h" #include "php_http_exception_object.h" #ifdef ZEND_ENGINE_2 @@ -1796,11 +1797,11 @@ PHP_METHOD(HttpRequest, setPutFile) char *file; int file_len; getObject(http_request_object, obj); - + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len)) { RETURN_FALSE; } - + UPD_PROP(obj, string, putFile, file); RETURN_TRUE; } @@ -2111,130 +2112,102 @@ PHP_METHOD(HttpRequest, getResponseMessage) PHP_METHOD(HttpRequest, send) { STATUS status = FAILURE; - zval *meth, *URL, *qdata, *opts, *info, *resp; - char *request_uri; + http_request_body body = {0}; getObject(http_request_object, obj); NO_ARGS; SET_EH_THROW_HTTP(); - if ((!obj->ch) && (!(obj->ch = curl_easy_init()))) { - http_error(E_WARNING, HTTP_E_CURL, "Could not initilaize curl"); + if (obj->attached) { + http_error(E_WARNING, HTTP_E_CURL, "You cannot call HttpRequest::send() while attached to an HttpRequestPool"); RETURN_FALSE; } - meth = GET_PROP(obj, method); - URL = GET_PROP(obj, url); - qdata = GET_PROP(obj, queryData); - opts = GET_PROP(obj, options); - info = GET_PROP(obj, responseInfo); - resp = GET_PROP(obj, responseData); - - // HTTP_URI_MAXLEN+1 long char * - if (!(request_uri = http_absolute_uri_ex(Z_STRVAL_P(URL), Z_STRLEN_P(URL), NULL, 0, NULL, 0, 0))) { - RETURN_FALSE; + if (SUCCESS == (status = http_request_object_requesthandler(obj, getThis(), &body))) { + zval *info = GET_PROP(obj, responseInfo); + status = http_request_exec(obj->ch, Z_ARRVAL_P(info)); + SET_PROP(obj, responseInfo, info); } + http_request_body_dtor(&body); - if (Z_STRLEN_P(qdata) && (strlen(request_uri) < HTTP_URI_MAXLEN)) { - if (!strchr(request_uri, '?')) { - strcat(request_uri, "?"); - } else { - strcat(request_uri, "&"); - } - strncat(request_uri, Z_STRVAL_P(qdata), HTTP_URI_MAXLEN - strlen(request_uri)); + /* final data handling */ + if (SUCCESS == status) { + status = http_request_object_responsehandler(obj, getThis(), NULL); } - switch (Z_LVAL_P(meth)) - { - case HTTP_GET: - case HTTP_HEAD: - status = http_request_ex(obj->ch, Z_LVAL_P(meth), request_uri, NULL, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response); - break; - - case HTTP_PUT: - { - http_request_body body; - php_stream *stream; - php_stream_statbuf ssb; - zval *file = GET_PROP(obj, putFile); - - if ( (stream = php_stream_open_wrapper(Z_STRVAL_P(file), "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL)) && - !php_stream_stat(stream, &ssb)) { - body.type = HTTP_REQUEST_BODY_UPLOADFILE; - body.data = stream; - body.size = ssb.sb.st_size; - - status = http_put_ex(obj->ch, request_uri, &body, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response); - http_request_body_dtor(&body); - } else { - status = FAILURE; - } - } - break; - - case HTTP_POST: - { - http_request_body body; - zval *fields = GET_PROP(obj, postFields), *files = GET_PROP(obj, postFiles); + SET_EH_NORMAL(); + RETURN_SUCCESS(status); +} +/* }}} */ - if (SUCCESS == (status = http_request_body_fill(&body, Z_ARRVAL_P(fields), Z_ARRVAL_P(files)))) { - status = http_post_ex(obj->ch, request_uri, &body, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response); - http_request_body_dtor(&body); - } - } - break; +/* {{{ HttpRequestPool */ - default: - { - http_request_body body; - zval *post = GET_PROP(obj, postData); +/* {{{ proto void HttpRequestPool::__construct(void) + * + * Instantiate a new HttpRequestPool object. + */ +PHP_METHOD(HttpRequestPool, __construct) +{ + NO_ARGS; +} +/* }}} */ - body.type = HTTP_REQUEST_BODY_CSTRING; - body.data = Z_STRVAL_P(post); - body.size = Z_STRLEN_P(post); +/* {{{ proto bool HttpRequestPool::attach(HttpRequest request) + * + * Attach an HttpRequest object to this HttpRequestPool. + * NOTE: set all options prior attaching! + */ +PHP_METHOD(HttpRequestPool, attach) +{ + zval *request; + STATUS status = FAILURE; + getObject(http_requestpool_object, obj); - status = http_request_ex(obj->ch, Z_LVAL_P(meth), request_uri, &body, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response); - } - break; + SET_EH_THROW_HTTP(); + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) { + status = http_request_pool_attach(&obj->pool, request); } + SET_EH_NORMAL(); + RETURN_SUCCESS(status); +} +/* }}} */ - efree(request_uri); - - /* final data handling */ - if (status == SUCCESS) { - http_message *msg; - - if (msg = http_message_parse(PHPSTR_VAL(&obj->response), PHPSTR_LEN(&obj->response))) { - zval *headers, *message; - char *body; - size_t body_len; - - UPD_PROP(obj, long, responseCode, msg->info.response.code); - - MAKE_STD_ZVAL(headers) - array_init(headers); - - zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); - phpstr_data(PHPSTR(msg), &body, &body_len); - - add_assoc_zval(resp, "headers", headers); - add_assoc_stringl(resp, "body", body, body_len, 0); +/* {{{ proto bool HttpRequestPool::detach(HttpRequest request) + * + * Detach an HttpRequest object from this HttpRequestPool. + */ +PHP_METHOD(HttpRequestPool, detach) +{ + zval *request; + STATUS status = FAILURE; + getObject(http_requestpool_object, obj); - message = GET_PROP(obj, responseMessage); - zval_dtor(message); - Z_TYPE_P(message) = IS_OBJECT; - message->value.obj = http_message_object_from_msg(msg); - SET_PROP(obj, responseMessage, message); - } else { - status = FAILURE; - } + SET_EH_THROW_HTTP(); + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) { + status = http_request_pool_detach(&obj->pool, request); } - SET_EH_NORMAL(); RETURN_SUCCESS(status); } /* }}} */ + +/* {{{ proto bool HttpRequestPool::send() + * + * Send all attached HttpRequest objects in parallel. + */ +PHP_METHOD(HttpRequestPool, send) +{ + getObject(http_requestpool_object, obj); + + NO_ARGS; + + RETURN_SUCCESS(http_request_pool_send(&obj->pool)); +} +/* }}} */ + +/* }}} */ + /* }}} */ #endif /* HTTP_HAVE_CURL */ diff --git a/http_request_api.c b/http_request_api.c index 534542f..8f2cb37 100644 --- a/http_request_api.c +++ b/http_request_api.c @@ -32,6 +32,8 @@ #include "php_http_std_defs.h" #include "php_http_api.h" #include "php_http_request_api.h" +#include "php_http_request_object.h" +#include "php_http_requestpool_object.h" #include "php_http_url_api.h" ZEND_EXTERN_MODULE_GLOBALS(http) @@ -48,7 +50,7 @@ ZEND_EXTERN_MODULE_GLOBALS(http) { \ char *c; \ if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_ ##I, &c)) { \ - add_assoc_string(&array, pretty_key(http_curl_copystr(#X), sizeof(#X)-1, 0, 0), c ? c : "", 1); \ + add_assoc_string(&array, pretty_key(http_request_copystr(#X), sizeof(#X)-1, 0, 0), c ? c : "", 1); \ } \ } \ break; \ @@ -57,7 +59,7 @@ ZEND_EXTERN_MODULE_GLOBALS(http) { \ double d; \ if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_ ##I, &d)) { \ - add_assoc_double(&array, pretty_key(http_curl_copystr(#X), sizeof(#X)-1, 0, 0), d); \ + add_assoc_double(&array, pretty_key(http_request_copystr(#X), sizeof(#X)-1, 0, 0), d); \ } \ } \ break; \ @@ -66,7 +68,7 @@ ZEND_EXTERN_MODULE_GLOBALS(http) { \ long l; \ if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_ ##I, &l)) { \ - add_assoc_long(&array, pretty_key(http_curl_copystr(#X), sizeof(#X)-1, 0, 0), l); \ + add_assoc_long(&array, pretty_key(http_request_copystr(#X), sizeof(#X)-1, 0, 0), l); \ } \ } \ break; \ @@ -79,7 +81,7 @@ ZEND_EXTERN_MODULE_GLOBALS(http) #define HTTP_CURL_OPT_STRING_EX(keyname, optname) \ if (!strcasecmp(key, #keyname)) { \ convert_to_string_ex(param); \ - HTTP_CURL_OPT(optname, http_curl_copystr(Z_STRVAL_PP(param))); \ + HTTP_CURL_OPT(optname, http_request_copystr(Z_STRVAL_PP(param))); \ key = NULL; \ continue; \ } @@ -96,8 +98,6 @@ ZEND_EXTERN_MODULE_GLOBALS(http) static const char *const http_request_methods[HTTP_MAX_REQUEST_METHOD + 1]; -#define http_curl_copystr(s) _http_curl_copystr((s) TSRMLS_CC) -static inline char *_http_curl_copystr(const char *str TSRMLS_DC); #define http_curl_getopt(o, k, t) _http_curl_getopt_ex((o), (k), sizeof(k), (t) TSRMLS_CC) #define http_curl_getopt_ex(o, k, l, t) _http_curl_getopt_ex((o), (k), (l), (t) TSRMLS_CC) static inline zval *_http_curl_getopt_ex(HashTable *options, char *key, size_t keylen, int type TSRMLS_DC); @@ -106,6 +106,27 @@ static size_t http_curl_read_callback(void *, size_t, size_t, void *); static int http_curl_progress_callback(void *, double, double, double, double); static int http_curl_debug_callback(CURL *, curl_infotype, char *, size_t, void *); +static void http_request_pool_freebody(http_request_body **body); +static void http_request_pool_responsehandler(zval **req TSRMLS_DC); +static inline STATUS http_request_pool_select(http_request_pool *pool); +static inline void http_request_pool_perform(http_request_pool *pool); + +/* {{{ char *http_request_copystr(char *) */ +PHP_HTTP_API char *_http_request_copystr(const char *str TSRMLS_DC) +{ + char *new_str = estrdup(str); + zend_llist_add_element(&HTTP_G(request).curl.copies, &new_str); + return new_str; +} +/* }}} */ + +/* {{{ http_request_body *http_request_body_new() */ +PHP_HTTP_API http_request_body *_http_request_body_new(TSRMLS_D) +{ + http_request_body *body = ecalloc(1, sizeof(http_request_body)); + return body; +} +/* }}} */ /* {{{ STATUS http_request_body_fill(http_request_body *body, HashTable *, HashTable *) */ PHP_HTTP_API STATUS _http_request_body_fill(http_request_body *body, HashTable *fields, HashTable *files TSRMLS_DC) @@ -186,50 +207,58 @@ PHP_HTTP_API STATUS _http_request_body_fill(http_request_body *body, HashTable * /* {{{ void http_request_body_dtor(http_request_body *) */ PHP_HTTP_API void _http_request_body_dtor(http_request_body *body TSRMLS_DC) { - switch (body->type) - { - case HTTP_REQUEST_BODY_CSTRING: - efree(body->data); - break; + if (body) { + switch (body->type) + { + case HTTP_REQUEST_BODY_CSTRING: + if (body->data) { + efree(body->data); + } + break; - case HTTP_REQUEST_BODY_CURLPOST: - curl_formfree(body->data); - break; + case HTTP_REQUEST_BODY_CURLPOST: + curl_formfree(body->data); + break; - case HTTP_REQUEST_BODY_UPLOADFILE: - php_stream_close(body->data); - break; + case HTTP_REQUEST_BODY_UPLOADFILE: + php_stream_close(body->data); + break; + } } } /* }}} */ -/* {{{ STATUS http_request_ex(CURL *, http_request_method, char *, http_request_body, HashTable, HashTable, phpstr *) */ -PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const char *url, http_request_body *body, HashTable *options, HashTable *info, phpstr *response TSRMLS_DC) +/* {{{ void http_request_body_free(http_request_body *) */ +PHP_HTTP_API void _http_request_body_free(http_request_body *body TSRMLS_DC) +{ + if (body) { + http_request_body_dtor(body); + efree(body); + } +} +/* }}} */ + +/* {{{ STATUS http_request_init(CURL *, http_request_method, char *, http_request_body *, HashTable *, phpstr *) */ +PHP_HTTP_API STATUS _http_request_init(CURL *ch, http_request_method meth, const char *url, http_request_body *body, HashTable *options, phpstr *response TSRMLS_DC) { - CURLcode result = CURLE_OK; - STATUS status = SUCCESS; - zend_bool clean_curl = 0, range_req = 0; zval *zoption; + zend_bool range_req = 0; - /* check/init CURL handle */ - if (ch) { + /* reset CURL handle */ #if LIBCURL_VERSION_NUM >= 0x070c01 - curl_easy_reset(ch); + curl_easy_reset(ch); #endif - } else { - if (ch = curl_easy_init()) { - clean_curl = 1; - } else { - http_error(E_WARNING, HTTP_E_CURL, "Could not initialize curl"); - return FAILURE; - } - } /* set options */ if (url) { HTTP_CURL_OPT(URL, url); } + if (response) { + HTTP_CURL_OPT(WRITEDATA, response); + HTTP_CURL_OPT(WRITEHEADER, response); + } + HTTP_CURL_OPT(HEADER, 0); HTTP_CURL_OPT(FILETIME, 1); HTTP_CURL_OPT(AUTOREFERER, 1); @@ -237,11 +266,6 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c HTTP_CURL_OPT(WRITEFUNCTION, http_curl_write_callback); HTTP_CURL_OPT(HEADERFUNCTION, http_curl_write_callback); - if (response) { - HTTP_CURL_OPT(WRITEDATA, response); - HTTP_CURL_OPT(WRITEHEADER, response); - } - #if defined(ZTS) && (LIBCURL_VERSION_NUM >= 0x070a00) HTTP_CURL_OPT(NOSIGNAL, 1); #endif @@ -269,14 +293,14 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c /* proxy */ if (zoption = http_curl_getopt(options, "proxyhost", IS_STRING)) { - HTTP_CURL_OPT(PROXY, http_curl_copystr(Z_STRVAL_P(zoption))); + HTTP_CURL_OPT(PROXY, http_request_copystr(Z_STRVAL_P(zoption))); /* port */ if (zoption = http_curl_getopt(options, "proxyport", IS_LONG)) { HTTP_CURL_OPT(PROXYPORT, Z_LVAL_P(zoption)); } /* user:pass */ if (zoption = http_curl_getopt(options, "proxyauth", IS_STRING)) { - HTTP_CURL_OPT(PROXYUSERPWD, http_curl_copystr(Z_STRVAL_P(zoption))); + HTTP_CURL_OPT(PROXYUSERPWD, http_request_copystr(Z_STRVAL_P(zoption))); } #if LIBCURL_VERSION_NUM >= 0x070a07 /* auth method */ @@ -288,7 +312,7 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c /* outgoing interface */ if (zoption = http_curl_getopt(options, "interface", IS_STRING)) { - HTTP_CURL_OPT(INTERFACE, http_curl_copystr(Z_STRVAL_P(zoption))); + HTTP_CURL_OPT(INTERFACE, http_request_copystr(Z_STRVAL_P(zoption))); } /* another port */ @@ -298,7 +322,7 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c /* auth */ if (zoption = http_curl_getopt(options, "httpauth", IS_STRING)) { - HTTP_CURL_OPT(USERPWD, http_curl_copystr(Z_STRVAL_P(zoption))); + HTTP_CURL_OPT(USERPWD, http_request_copystr(Z_STRVAL_P(zoption))); } #if LIBCURL_VERSION_NUM >= 0x070a06 if (zoption = http_curl_getopt(options, "httpauthtype", IS_LONG)) { @@ -309,7 +333,7 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c /* compress, empty string enables deflate and gzip */ if (zoption = http_curl_getopt(options, "compress", IS_BOOL)) { if (Z_LVAL_P(zoption)) { - HTTP_CURL_OPT(ENCODING, http_curl_copystr("")); + HTTP_CURL_OPT(ENCODING, http_request_copystr("")); } } @@ -326,12 +350,12 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c /* referer */ if (zoption = http_curl_getopt(options, "referer", IS_STRING)) { - HTTP_CURL_OPT(REFERER, http_curl_copystr(Z_STRVAL_P(zoption))); + HTTP_CURL_OPT(REFERER, http_request_copystr(Z_STRVAL_P(zoption))); } /* useragent, default "PECL::HTTP/version (PHP/version)" */ if (zoption = http_curl_getopt(options, "useragent", IS_STRING)) { - HTTP_CURL_OPT(USERAGENT, http_curl_copystr(Z_STRVAL_P(zoption))); + HTTP_CURL_OPT(USERAGENT, http_request_copystr(Z_STRVAL_P(zoption))); } else { HTTP_CURL_OPT(USERAGENT, "PECL::HTTP/" HTTP_PEXT_VERSION " (PHP/" PHP_VERSION ")"); } @@ -348,7 +372,7 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void **) &header_val)) { char header[1024] = {0}; snprintf(header, 1023, "%s: %s", header_key, Z_STRVAL_PP(header_val)); - headers = curl_slist_append(headers, http_curl_copystr(header)); + headers = curl_slist_append(headers, http_request_copystr(header)); } /* reset */ @@ -381,15 +405,15 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c if (qstr->used) { phpstr_fix(qstr); - HTTP_CURL_OPT(COOKIE, http_curl_copystr(qstr->data)); + HTTP_CURL_OPT(COOKIE, http_request_copystr(qstr->data)); } phpstr_free(qstr); } /* cookiestore */ if (zoption = http_curl_getopt(options, "cookiestore", IS_STRING)) { - HTTP_CURL_OPT(COOKIEFILE, http_curl_copystr(Z_STRVAL_P(zoption))); - HTTP_CURL_OPT(COOKIEJAR, http_curl_copystr(Z_STRVAL_P(zoption))); + HTTP_CURL_OPT(COOKIEFILE, http_request_copystr(Z_STRVAL_P(zoption))); + HTTP_CURL_OPT(COOKIEJAR, http_request_copystr(Z_STRVAL_P(zoption))); } /* resume */ @@ -488,8 +512,7 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c curl_easy_setopt(ch, CURLOPT_CUSTOMREQUEST, http_request_method_name(meth)); } else { http_error_ex(E_WARNING, HTTP_E_CURL, "Unsupported request method: %d", meth); - status = FAILURE; - goto http_request_end; + return FAILURE; } break; } @@ -515,86 +538,95 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c default: http_error_ex(E_WARNING, HTTP_E_CURL, "Unknown request body type: %d", body->type); - status = FAILURE; - goto http_request_end; + return FAILURE; break; } } + return SUCCESS; +} +/* }}} */ + +/* {{{ STATUS http_request_exec(CURL *, HashTable *) */ +PHP_HTTP_API STATUS _http_request_exec(CURL *ch, HashTable *info TSRMLS_DC) +{ + CURLcode result; + /* perform request */ - if (CURLE_OK == (result = curl_easy_perform(ch))) { + if (CURLE_OK != (result = curl_easy_perform(ch))) { + http_error_ex(E_WARNING, HTTP_E_CURL, "Could not perform request: %s", curl_easy_strerror(result)); + return FAILURE; + } else { /* get curl info */ if (info) { - zval array; - Z_ARRVAL(array) = info; + http_request_info(ch, info); + } + return SUCCESS; + } +} +/* }}} */ + +/* {{{ void http_request_info(CURL *, HashTable *) */ +PHP_HTTP_API void _http_request_info(CURL *ch, HashTable *info TSRMLS_DC) +{ + zval array; + Z_ARRVAL(array) = info; - HTTP_CURL_INFO(EFFECTIVE_URL); + HTTP_CURL_INFO(EFFECTIVE_URL); #if LIBCURL_VERSION_NUM >= 0x070a07 - HTTP_CURL_INFO(RESPONSE_CODE); + HTTP_CURL_INFO(RESPONSE_CODE); #else - HTTP_CURL_INFO_EX(HTTP_CODE, RESPONSE_CODE); + HTTP_CURL_INFO_EX(HTTP_CODE, RESPONSE_CODE); #endif - HTTP_CURL_INFO(HTTP_CONNECTCODE); + HTTP_CURL_INFO(HTTP_CONNECTCODE); #if LIBCURL_VERSION_NUM >= 0x070500 - HTTP_CURL_INFO(FILETIME); + HTTP_CURL_INFO(FILETIME); #endif - HTTP_CURL_INFO(TOTAL_TIME); - HTTP_CURL_INFO(NAMELOOKUP_TIME); - HTTP_CURL_INFO(CONNECT_TIME); - HTTP_CURL_INFO(PRETRANSFER_TIME); - HTTP_CURL_INFO(STARTTRANSFER_TIME); + HTTP_CURL_INFO(TOTAL_TIME); + HTTP_CURL_INFO(NAMELOOKUP_TIME); + HTTP_CURL_INFO(CONNECT_TIME); + HTTP_CURL_INFO(PRETRANSFER_TIME); + HTTP_CURL_INFO(STARTTRANSFER_TIME); #if LIBCURL_VERSION_NUM >= 0x070907 - HTTP_CURL_INFO(REDIRECT_TIME); - HTTP_CURL_INFO(REDIRECT_COUNT); + HTTP_CURL_INFO(REDIRECT_TIME); + HTTP_CURL_INFO(REDIRECT_COUNT); #endif - HTTP_CURL_INFO(SIZE_UPLOAD); - HTTP_CURL_INFO(SIZE_DOWNLOAD); - HTTP_CURL_INFO(SPEED_DOWNLOAD); - HTTP_CURL_INFO(SPEED_UPLOAD); - HTTP_CURL_INFO(HEADER_SIZE); - HTTP_CURL_INFO(REQUEST_SIZE); - HTTP_CURL_INFO(SSL_VERIFYRESULT); + HTTP_CURL_INFO(SIZE_UPLOAD); + HTTP_CURL_INFO(SIZE_DOWNLOAD); + HTTP_CURL_INFO(SPEED_DOWNLOAD); + HTTP_CURL_INFO(SPEED_UPLOAD); + HTTP_CURL_INFO(HEADER_SIZE); + HTTP_CURL_INFO(REQUEST_SIZE); + HTTP_CURL_INFO(SSL_VERIFYRESULT); #if LIBCURL_VERSION_NUM >= 0x070c03 - /*HTTP_CURL_INFO(SSL_ENGINES); todo: CURLINFO_SLIST */ + /*HTTP_CURL_INFO(SSL_ENGINES); todo: CURLINFO_SLIST */ #endif - HTTP_CURL_INFO(CONTENT_LENGTH_DOWNLOAD); - HTTP_CURL_INFO(CONTENT_LENGTH_UPLOAD); - HTTP_CURL_INFO(CONTENT_TYPE); + HTTP_CURL_INFO(CONTENT_LENGTH_DOWNLOAD); + HTTP_CURL_INFO(CONTENT_LENGTH_UPLOAD); + HTTP_CURL_INFO(CONTENT_TYPE); #if LIBCURL_VERSION_NUM >= 0x070a03 - /*HTTP_CURL_INFO(PRIVATE);*/ + /*HTTP_CURL_INFO(PRIVATE);*/ #endif #if LIBCURL_VERSION_NUM >= 0x070a08 - HTTP_CURL_INFO(HTTPAUTH_AVAIL); - HTTP_CURL_INFO(PROXYAUTH_AVAIL); + HTTP_CURL_INFO(HTTPAUTH_AVAIL); + HTTP_CURL_INFO(PROXYAUTH_AVAIL); #endif #if LIBCURL_VERSION_NUM >= 0x070c02 - /*HTTP_CURL_INFO(OS_ERRNO);*/ + /*HTTP_CURL_INFO(OS_ERRNO);*/ #endif #if LIBCURL_VERSION_NUM >= 0x070c03 - HTTP_CURL_INFO(NUM_CONNECTS); + HTTP_CURL_INFO(NUM_CONNECTS); #endif - } - } else { - http_error_ex(E_WARNING, HTTP_E_CURL, "Could not perform request: %s", curl_easy_strerror(result)); - status = FAILURE; - } - -http_request_end: - /* free strings copied with http_curl_copystr() */ - zend_llist_clean(&HTTP_G(request).curl.copies); - - /* clean curl handle if acquired */ - if (clean_curl) { - curl_easy_cleanup(ch); - ch = NULL; - } +} +/* }}} */ - /* finalize response */ - if (response) { - phpstr_fix(PHPSTR(response)); +/* {{{ STATUS http_request_ex(CURL *, http_request_method, char *, http_request_body, HashTable, HashTable, phpstr *) */ +PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const char *url, http_request_body *body, HashTable *options, HashTable *info, phpstr *response TSRMLS_DC) +{ + if (SUCCESS != http_request_init(ch, meth, url, body, options, response)) { + return FAILURE; } - - return status; + return http_request_exec(ch, info); } /* }}} */ @@ -687,6 +719,143 @@ PHP_HTTP_API STATUS _http_request_method_unregister(unsigned long method TSRMLS_ } /* }}} */ + +/* {{{ http_request_pool *http_request_pool_init(http_request_pool *) */ +PHP_HTTP_API http_request_pool *_http_request_pool_init(http_request_pool *pool TSRMLS_DC) +{ + zend_bool free_pool; + + if ((free_pool = (!pool))) { + pool = emalloc(sizeof(http_request_pool)); + pool->ch = NULL; + } + + if (!pool->ch) { + if (!(pool->ch = curl_multi_init())) { + http_error(E_WARNING, HTTP_E_CURL, "Could not initialize curl"); + if (free_pool) { + efree(pool); + } + return NULL; + } + } + + pool->unfinished = 0; + zend_llist_init(&pool->handles, sizeof(zval *), (llist_dtor_func_t) ZVAL_PTR_DTOR, 0); + zend_llist_init(&pool->bodies, sizeof(http_request_body *), (llist_dtor_func_t) http_request_pool_freebody, 0); + + return pool; +} +/* }}} */ + +/* {{{ STATUS http_request_pool_attach(http_request_pool *, zval *) */ +PHP_HTTP_API STATUS _http_request_pool_attach(http_request_pool *pool, zval *request TSRMLS_DC) +{ + getObjectEx(http_request_object, req, request); + + if (req->attached) { + http_error(E_WARNING, HTTP_E_CURL, "HttpRequest object is already member of an HttpRequestPool"); + } else { + CURLMcode code; + http_request_body *body = http_request_body_new(); + zval *info = GET_PROP_EX(req, request, responseInfo); + + if (SUCCESS != http_request_object_requesthandler(req, request, body)) { + efree(body); + http_error_ex(E_WARNING, HTTP_E_CURL, "Could not initialize HttpRequest object for attaching to the HttpRequestPool"); + } else if (CURLM_OK != (code = curl_multi_add_handle(pool->ch, req->ch))) { + http_error_ex(E_WARNING, HTTP_E_CURL, "Could not attach HttpRequest object to the HttpRequestPool: %s", curl_multi_strerror(code)); + } else { + req->attached = 1; + zval_add_ref(&request); + zend_llist_add_element(&pool->handles, &request); + zend_llist_add_element(&pool->bodies, &body); + return SUCCESS; + } + } + return FAILURE; +} +/* }}} */ + +/* {{{ STATUS http_request_pool_detach(http_request_pool *, zval *) */ +PHP_HTTP_API STATUS _http_request_pool_detach(http_request_pool *pool, zval *request TSRMLS_DC) +{ + getObjectEx(http_request_object, req, request); + + if (!req->attached) { + http_error(E_WARNING, HTTP_E_CURL, "HttpRequest object is not attached to an HttpRequestPool"); + } else { + CURLMcode code; + + if (CURLM_OK != (code = curl_multi_remove_handle(pool->ch, req->ch))) { + http_error_ex(E_WARNING, HTTP_E_CURL, "Could not detach HttpRequest object from the HttpRequestPool: %s", curl_multi_strerror(code)); + } else { + req->attached = 0; + zval_ptr_dtor(&request); + return SUCCESS; + } + } + return FAILURE; +} +/* }}} */ + +/* {{{ STATUS http_request_pool_send(http_request_pool *) */ +PHP_HTTP_API STATUS _http_request_pool_send(http_request_pool *pool TSRMLS_DC) +{ + http_request_pool_perform(pool); + while (pool->unfinished) { + if (SUCCESS != http_request_pool_select(pool)) { + http_error(E_WARNING, HTTP_E_CURL, "Socket error"); + return FAILURE; + } + http_request_pool_perform(pool); + } + zend_llist_apply(&pool->handles, (llist_apply_func_t) http_request_pool_responsehandler TSRMLS_CC); + return SUCCESS; +} +/* }}} */ + +/*#*/ + +/* {{{ static void http_request_pool_free_body(http_request_body *) */ +static void http_request_pool_freebody(http_request_body **body) +{ + TSRMLS_FETCH(); + http_request_body_free(*body); +} +/* }}} */ + +/* {{{ static void http_request_pool_responsehandler(zval **) */ +static void http_request_pool_responsehandler(zval **req TSRMLS_DC) +{ + getObjectEx(http_request_object, obj, *req); + http_request_object_responsehandler(obj, *req, NULL); +} +/* }}} */ + +/* {{{ static inline STATUS http_request_pool_select(http_request_pool *) */ +static inline STATUS http_request_pool_select(http_request_pool *pool) +{ + int MAX; + fd_set R, W, E; + struct timeval timeout = {1, 0}; + + FD_ZERO(&R); + FD_ZERO(&W); + FD_ZERO(&E); + + curl_multi_fdset(pool->ch, &R, &W, &E, &MAX); + return (-1 != select(MAX + 1, &R, &W, &E, &timeout)) ? SUCCESS : FAILURE; +} +/* }}} */ + +/* {{{ static inline void http_request_pool_perform(http_request_pool *) */ +static inline void http_request_pool_perform(http_request_pool *pool) +{ + while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(pool->ch, &pool->unfinished)); +} +/* }}} */ + /* {{{ char *http_request_methods[] */ static const char *const http_request_methods[] = { "UNKOWN", @@ -725,15 +894,6 @@ static const char *const http_request_methods[] = { }; /* }}} */ -/* {{{ static inline char *http_curl_copystr(char *) */ -static inline char *_http_curl_copystr(const char *str TSRMLS_DC) -{ - char *new_str = estrdup(str); - zend_llist_add_element(&HTTP_G(request).curl.copies, &new_str); - return new_str; -} -/* }}} */ - /* {{{ static size_t http_curl_write_callback(char *, size_t, size_t, void *) */ static size_t http_curl_write_callback(char *buf, size_t len, size_t n, void *s) { diff --git a/http_request_object.c b/http_request_object.c index d9dd8f2..f43d3ad 100644 --- a/http_request_object.c +++ b/http_request_object.c @@ -32,6 +32,10 @@ #include "php_http_std_defs.h" #include "php_http_request_object.h" #include "php_http_request_api.h" +#include "php_http_api.h" +#include "php_http_url_api.h" +#include "php_http_message_api.h" +#include "php_http_message_object.h" #ifdef ZEND_ENGINE_2 #ifdef HTTP_HAVE_CURL @@ -85,7 +89,7 @@ zend_function_entry http_request_object_fe[] = { PHP_ME(HttpRequest, setPutFile, NULL, ZEND_ACC_PUBLIC) PHP_ME(HttpRequest, getPutFile, NULL, ZEND_ACC_PUBLIC) PHP_ME(HttpRequest, unsetPutFile, NULL, ZEND_ACC_PUBLIC) - + PHP_ME(HttpRequest, send, NULL, ZEND_ACC_PUBLIC) PHP_ME(HttpRequest, getResponseData, NULL, ZEND_ACC_PUBLIC) @@ -152,6 +156,7 @@ zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC) o = ecalloc(1, sizeof(http_request_object)); o->zo.ce = ce; o->ch = curl_easy_init(); + o->attached = 0; phpstr_init_ex(&o->response, HTTP_CURLBUF_SIZE, 0); @@ -200,6 +205,131 @@ void _http_request_object_free(zend_object *object TSRMLS_DC) efree(o); } +STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_ptr, http_request_body *body TSRMLS_DC) +{ + zval *meth, *URL, *qdata, *opts; + char *request_uri, *uri; + STATUS status; + + if (!body) { + return FAILURE; + } + if ((!obj->ch) && (!(obj->ch = curl_easy_init()))) { + http_error(E_WARNING, HTTP_E_CURL, "Could not initilaize curl"); + return FAILURE; + } + + meth = GET_PROP(obj, method); + URL = GET_PROP(obj, url); + qdata = GET_PROP(obj, queryData); + opts = GET_PROP(obj, options); + + // HTTP_URI_MAXLEN+1 long char * + if (!(request_uri = http_absolute_uri_ex(Z_STRVAL_P(URL), Z_STRLEN_P(URL), NULL, 0, NULL, 0, 0))) { + return FAILURE; + } + + if (Z_STRLEN_P(qdata) && (strlen(request_uri) < HTTP_URI_MAXLEN)) { + if (!strchr(request_uri, '?')) { + strcat(request_uri, "?"); + } else { + strcat(request_uri, "&"); + } + strncat(request_uri, Z_STRVAL_P(qdata), HTTP_URI_MAXLEN - strlen(request_uri)); + } + + uri = http_request_copystr(request_uri); + efree(request_uri); + + switch (Z_LVAL_P(meth)) + { + case HTTP_GET: + case HTTP_HEAD: + body->type = -1; + status = http_request_init(obj->ch, Z_LVAL_P(meth), uri, NULL, Z_ARRVAL_P(opts), &obj->response); + break; + + case HTTP_PUT: + { + php_stream *stream; + php_stream_statbuf ssb; + zval *file = GET_PROP(obj, putFile); + + if ( (stream = php_stream_open_wrapper(Z_STRVAL_P(file), "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL)) && + !php_stream_stat(stream, &ssb)) { + body->type = HTTP_REQUEST_BODY_UPLOADFILE; + body->data = stream; + body->size = ssb.sb.st_size; + + status = http_request_init(obj->ch, HTTP_PUT, uri, body, Z_ARRVAL_P(opts), &obj->response); + } else { + status = FAILURE; + } + } + break; + + case HTTP_POST: + { + zval *fields = GET_PROP(obj, postFields), *files = GET_PROP(obj, postFiles); + + if (SUCCESS == (status = http_request_body_fill(body, Z_ARRVAL_P(fields), Z_ARRVAL_P(files)))) { + status = http_request_init(obj->ch, HTTP_POST, uri, body, Z_ARRVAL_P(opts), &obj->response); + } + } + break; + + default: + { + zval *post = GET_PROP(obj, postData); + + body->type = HTTP_REQUEST_BODY_CSTRING; + body->data = Z_STRVAL_P(post); + body->size = Z_STRLEN_P(post); + + status = http_request_init(obj->ch, Z_LVAL_P(meth), uri, body, Z_ARRVAL_P(opts), &obj->response); + } + break; + } + + return status; +} + +STATUS _http_request_object_responsehandler(http_request_object *obj, zval *this_ptr, HashTable *info TSRMLS_DC) +{ + http_message *msg; + + phpstr_fix(&obj->response); + + if (msg = http_message_parse(PHPSTR_VAL(&obj->response), PHPSTR_LEN(&obj->response))) { + char *body; + size_t body_len; + zval *headers, *message = GET_PROP(obj, responseMessage), *resp = GET_PROP(obj, responseData); + + UPD_PROP(obj, long, responseCode, msg->info.response.code); + + MAKE_STD_ZVAL(headers) + array_init(headers); + + zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); + phpstr_data(PHPSTR(msg), &body, &body_len); + + add_assoc_zval(resp, "headers", headers); + add_assoc_stringl(resp, "body", body, body_len, 0); + + //zval_dtor(&message); + Z_TYPE_P(message) = IS_OBJECT; + message->value.obj = http_message_object_from_msg(msg); + SET_PROP(obj, responseMessage, message); + + if (info) { + http_request_info(obj->ch, info); + } + + return SUCCESS; + } + return FAILURE; +} + #endif /* HTTP_HAVE_CURL */ #endif /* ZEND_ENGINE_2 */ diff --git a/http_requestpool_object.c b/http_requestpool_object.c new file mode 100644 index 0000000..09fc261 --- /dev/null +++ b/http_requestpool_object.c @@ -0,0 +1,110 @@ +/* + +----------------------------------------------------------------------+ + | PECL :: http | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, that | + | is bundled with this package in the file LICENSE, and is available | + | through the world-wide-web at http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Copyright (c) 2004-2005 Michael Wallner | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HTTP_HAVE_CURL +# ifdef PHP_WIN32 +# include +# endif +# include +#endif + +#include "php.h" + +#include "php_http_std_defs.h" +#include "php_http_requestpool_object.h" +#include "php_http_request_api.h" + +#ifdef ZEND_ENGINE_2 +#ifdef HTTP_HAVE_CURL + +#define http_requestpool_object_declare_default_properties() _http_requestpool_object_declare_default_properties(TSRMLS_C) +static inline void _http_requestpool_object_declare_default_properties(TSRMLS_D); + +zend_class_entry *http_requestpool_object_ce; +zend_function_entry http_requestpool_object_fe[] = { + PHP_ME(HttpRequestPool, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) + PHP_ME(HttpRequestPool, attach, NULL, ZEND_ACC_PUBLIC) + PHP_ME(HttpRequestPool, detach, NULL, ZEND_ACC_PUBLIC) + PHP_ME(HttpRequestPool, send, NULL, ZEND_ACC_PUBLIC) + + {NULL, NULL, NULL} +}; +static zend_object_handlers http_requestpool_object_handlers; + +void _http_requestpool_object_init(INIT_FUNC_ARGS) +{ + HTTP_REGISTER_CLASS_EX(HttpRequestPool, http_requestpool_object, NULL, 0); +} + +zend_object_value _http_requestpool_object_new(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value ov; + http_requestpool_object *o; + + o = ecalloc(1, sizeof(http_requestpool_object)); + o->zo.ce = ce; + + http_request_pool_init(&o->pool); + + ALLOC_HASHTABLE(OBJ_PROP(o)); + zend_hash_init(OBJ_PROP(o), 0, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); + + ov.handle = zend_objects_store_put(o, (zend_objects_store_dtor_t) zend_objects_destroy_object, http_requestpool_object_free, NULL TSRMLS_CC); + ov.handlers = &http_requestpool_object_handlers; + + return ov; +} + +static inline void _http_requestpool_object_declare_default_properties(TSRMLS_D) +{ + zend_class_entry *ce = http_requestpool_object_ce; + + DCL_PROP_N(PROTECTED, pool); +} + +void _http_requestpool_object_free(zend_object *object TSRMLS_DC) +{ + http_requestpool_object *o = (http_requestpool_object *) object; + + if (OBJ_PROP(o)) { + zend_hash_destroy(OBJ_PROP(o)); + FREE_HASHTABLE(OBJ_PROP(o)); + } + if (o->pool.ch) { + curl_multi_cleanup(o->pool.ch); + } + efree(o); +} + +#endif /* HTTP_HAVE_CURL */ +#endif /* ZEND_ENGINE_2 */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ + diff --git a/php_http_request_api.h b/php_http_request_api.h index bee4e70..25b2232 100644 --- a/php_http_request_api.h +++ b/php_http_request_api.h @@ -66,16 +66,26 @@ typedef enum { #define HTTP_STD_REQUEST_METHOD(m) ((m > HTTP_NO_REQUEST_METHOD) && (m < HTTP_MAX_REQUEST_METHOD)) #define HTTP_CUSTOM_REQUEST_METHOD(m) (m - HTTP_MAX_REQUEST_METHOD) -#define HTTP_REQUEST_BODY_CSTRING 0 -#define HTTP_REQUEST_BODY_CURLPOST 1 -#define HTTP_REQUEST_BODY_UPLOADFILE 2 -#define HTTP_REQUEST_BODY_UPLOADDATA 3 +#define HTTP_REQUEST_BODY_CSTRING 1 +#define HTTP_REQUEST_BODY_CURLPOST 2 +#define HTTP_REQUEST_BODY_UPLOADFILE 3 +#define HTTP_REQUEST_BODY_UPLOADDATA 4 typedef struct { int type; void *data; size_t size; } http_request_body; +typedef struct { + CURLM *ch; + zend_llist handles; + zend_llist bodies; + int unfinished; +} http_request_pool; + +#define http_request_copystr(s) _http_request_copystr((s) TSRMLS_CC) +PHP_HTTP_API char *_http_request_copystr(const char *string TSRMLS_DC); + #define http_request_method_name(m) _http_request_method_name((m) TSRMLS_CC) PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC); @@ -88,12 +98,39 @@ PHP_HTTP_API unsigned long _http_request_method_register(const char *method TSRM #define http_request_method_unregister(mn) _http_request_method_unregister((mn) TSRMLS_CC) PHP_HTTP_API STATUS _http_request_method_unregister(unsigned long method TSRMLS_DC); +#define http_request_body_new() _http_request_body_new(TSRMLS_C) +PHP_HTTP_API http_request_body *_http_request_body_new(TSRMLS_D); + #define http_request_body_fill(b, fields, files) _http_request_body_fill((b), (fields), (files) TSRMLS_CC) PHP_HTTP_API STATUS _http_request_body_fill(http_request_body *body, HashTable *fields, HashTable *files TSRMLS_DC); #define http_request_body_dtor(b) _http_request_body_dtor((b) TSRMLS_CC) PHP_HTTP_API void _http_request_body_dtor(http_request_body *body TSRMLS_DC); +#define http_request_body_free(b) _http_request_body_free((b) TSRMLS_CC) +PHP_HTTP_API void _http_request_body_free(http_request_body *body TSRMLS_DC); + +#define http_request_pool_init(p) _http_request_pool_init((p) TSRMLS_CC) +PHP_HTTP_API http_request_pool *_http_request_pool_init(http_request_pool *pool TSRMLS_DC); + +#define http_request_pool_attach(p, r) _http_request_pool_attach((p), (r) TSRMLS_CC) +PHP_HTTP_API STATUS _http_request_pool_attach(http_request_pool *pool, zval *request TSRMLS_DC); + +#define http_request_pool_detach(p, r) _http_request_pool_detach((p), (r) TSRMLS_CC) +PHP_HTTP_API STATUS _http_request_pool_detach(http_request_pool *pool, zval *request TSRMLS_DC); + +#define http_request_pool_send(p) _http_request_pool_send((p) TSRMLS_CC) +PHP_HTTP_API STATUS _http_request_pool_send(http_request_pool *pool TSRMLS_DC); + +#define http_request_init(ch, meth, url, body, options, response) _http_request_init((ch), (meth), (url), (body), (options), (response) TSRMLS_CC) +PHP_HTTP_API STATUS _http_request_init(CURL *ch, http_request_method meth, const char *url, http_request_body *body, HashTable *options, phpstr *response TSRMLS_DC); + +#define http_request_exec(ch, i) _http_request_exec((ch), (i) TSRMLS_CC) +PHP_HTTP_API STATUS _http_request_exec(CURL *ch, HashTable *info TSRMLS_DC); + +#define http_request_info(ch, i) _http_request_info((ch), (i) TSRMLS_CC) +PHP_HTTP_API void _http_request_info(CURL *ch, HashTable *info TSRMLS_DC); + #define http_request(meth, url, body, opt, info, resp) _http_request_ex(NULL, (meth), (url), (body), (opt), (info), (resp) TSRMLS_CC) #define http_request_ex(ch, meth, url, body, opt, info, resp) _http_request_ex((ch), (meth), (url), (body), (opt), (info), (resp) TSRMLS_CC) PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const char *URL, http_request_body *body, HashTable *options, HashTable *info, phpstr *response TSRMLS_DC); diff --git a/php_http_request_object.h b/php_http_request_object.h index 57051b7..e8326b3 100644 --- a/php_http_request_object.h +++ b/php_http_request_object.h @@ -26,11 +26,13 @@ #include +#include "php_http_request_api.h" #include "phpstr/phpstr.h" typedef struct { zend_object zo; CURL *ch; + zend_bool attached; phpstr response; } http_request_object; @@ -44,6 +46,11 @@ extern zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC #define http_request_object_free _http_request_object_free extern void _http_request_object_free(zend_object *object TSRMLS_DC); +#define http_request_object_requesthandler(req, this, body) _http_request_object_requesthandler((req), (this), (body) TSRMLS_CC) +extern STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_ptr, http_request_body *body TSRMLS_DC); +#define http_request_object_responsehandler(req, this, info) _http_request_object_responsehandler((req), (this), (info) TSRMLS_CC) +extern STATUS _http_request_object_responsehandler(http_request_object *obj, zval *this_ptr, HashTable *info TSRMLS_DC); + PHP_METHOD(HttpRequest, __construct); PHP_METHOD(HttpRequest, __destruct); PHP_METHOD(HttpRequest, setOptions); diff --git a/php_http_requestpool_object.h b/php_http_requestpool_object.h new file mode 100644 index 0000000..1981c85 --- /dev/null +++ b/php_http_requestpool_object.h @@ -0,0 +1,63 @@ +/* + +----------------------------------------------------------------------+ + | PECL :: http | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, that | + | is bundled with this package in the file LICENSE, and is available | + | through the world-wide-web at http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Copyright (c) 2004-2005 Michael Wallner | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifndef PHP_HTTP_REQUESTPOOL_OBJECT_H +#define PHP_HTTP_REQUESTPOOL_OBJECT_H +#ifdef HTTP_HAVE_CURL +#ifdef ZEND_ENGINE_2 + +#ifdef PHP_WIN32 +# include +#endif + +#include + +#include "php_http_request_api.h" + +typedef struct { + zend_object zo; + http_request_pool pool; +} http_requestpool_object; + +extern zend_class_entry *http_requestpool_object_ce; +extern zend_function_entry http_requestpool_object_fe[]; + +#define http_requestpool_object_init() _http_requestpool_object_init(INIT_FUNC_ARGS_PASSTHRU) +extern void _http_requestpool_object_init(INIT_FUNC_ARGS); +#define http_requestpool_object_new _http_requestpool_object_new +extern zend_object_value _http_requestpool_object_new(zend_class_entry *ce TSRMLS_DC); +#define http_requestpool_object_free _http_requestpool_object_free +extern void _http_requestpool_object_free(zend_object *object TSRMLS_DC); + +PHP_METHOD(HttpRequestPool, __construct); +PHP_METHOD(HttpRequestPool, attach); +PHP_METHOD(HttpRequestPool, detach); +PHP_METHOD(HttpRequestPool, send); + +#endif +#endif +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ + diff --git a/php_http_std_defs.h b/php_http_std_defs.h index 42b67ed..0e0bc14 100644 --- a/php_http_std_defs.h +++ b/php_http_std_defs.h @@ -199,9 +199,12 @@ typedef int STATUS; # define DCL_PROP(a, t, n, v) zend_declare_property_ ##t(ce, (#n), sizeof(#n), (v), (ZEND_ACC_ ##a) TSRMLS_CC) # define DCL_PROP_Z(a, n, v) zend_declare_property(ce, (#n), sizeof(#n), (v), (ZEND_ACC_ ##a) TSRMLS_CC) # define DCL_PROP_N(a, n) zend_declare_property_null(ce, (#n), sizeof(#n), (ZEND_ACC_ ##a) TSRMLS_CC) -# define UPD_PROP(o, t, n, v) zend_update_property_ ##t(o->zo.ce, getThis(), (#n), sizeof(#n), (v) TSRMLS_CC) -# define SET_PROP(o, n, z) zend_update_property(o->zo.ce, getThis(), (#n), sizeof(#n), (z) TSRMLS_CC) -# define GET_PROP(o, n) zend_read_property(o->zo.ce, getThis(), (#n), sizeof(#n), 0 TSRMLS_CC) +# define UPD_PROP(o, t, n, v) UPD_PROP_EX(o, getThis(), t, n, v) +# define UPD_PROP_EX(o, this, t, n, v) zend_update_property_ ##t(o->zo.ce, this, (#n), sizeof(#n), (v) TSRMLS_CC) +# define SET_PROP(o, n, z) SET_PROP_EX(o, getThis(), n, z) +# define SET_PROP_EX(o, this, n, z) zend_update_property(o->zo.ce, this, (#n), sizeof(#n), (z) TSRMLS_CC) +# define GET_PROP(o, n) GET_PROP_EX(o, getThis(), n) +# define GET_PROP_EX(o, this, n) zend_read_property(o->zo.ce, this, (#n), sizeof(#n), 0 TSRMLS_CC) # define INIT_PARR(o, n) \ { \