From: Sterling Hughes Date: Wed, 13 Nov 2002 22:25:33 +0000 (+0000) Subject: add multi support and reorganize things a bit... X-Git-Tag: BEFORE_RENAMING~67 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=537284418cde811f6541708a928430c7967d4a27;p=php add multi support and reorganize things a bit... --- diff --git a/ext/curl/CREDITS b/ext/curl/CREDITS index 1e9f272a39..610e036787 100644 --- a/ext/curl/CREDITS +++ b/ext/curl/CREDITS @@ -1,2 +1,2 @@ -CURL +cURL Sterling Hughes diff --git a/ext/curl/config.m4 b/ext/curl/config.m4 index 5841c173df..505f7b0104 100644 --- a/ext/curl/config.m4 +++ b/ext/curl/config.m4 @@ -1,5 +1,5 @@ dnl -dnl $Id$ +dnl $Id$ dnl PHP_ARG_WITH(curl, for CURL support, @@ -29,7 +29,7 @@ if test "$PHP_CURL" != "no"; then fi CURL_CONFIG="curl-config" - AC_MSG_CHECKING(for cURL 7.9.8 or greater) + AC_MSG_CHECKING(for cURL 7.10.2 or greater) if ${CURL_DIR}/bin/curl-config --libs print > /dev/null 2>&1; then CURL_CONFIG=${CURL_DIR}/bin/curl-config @@ -41,11 +41,11 @@ if test "$PHP_CURL" != "no"; then curl_version_full=`$CURL_CONFIG --version` curl_version=`echo ${curl_version_full} | sed -e 's/libcurl //' | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'` - if test "$curl_version" -ge 7009008; then + if test "$curl_version" -ge 7010002; then AC_MSG_RESULT($curl_version_full) CURL_LIBS=`$CURL_CONFIG --libs` else - AC_MSG_ERROR(cURL version 7.9.8 or later is required to compile php with cURL support) + AC_MSG_ERROR(cURL version 7.10.2 or later is required to compile php with cURL support) fi PHP_ADD_INCLUDE($CURL_DIR/include) @@ -72,6 +72,6 @@ dnl if test "$PHP_CURLWRAPPERS" != "no" ; then dnl AC_DEFINE(PHP_CURL_URL_WRAPPERS,1,[ ]) dnl fi - PHP_NEW_EXTENSION(curl, curl.c curlstreams.c, $ext_shared) + PHP_NEW_EXTENSION(curl, interface.c multi.c streams.c, $ext_shared) PHP_SUBST(CURL_SHARED_LIBADD) fi diff --git a/ext/curl/curl.dsp b/ext/curl/curl.dsp index 66095f0b8a..d0a7167a9b 100644 --- a/ext/curl/curl.dsp +++ b/ext/curl/curl.dsp @@ -158,8 +158,17 @@ LINK32=link.exe # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File -SOURCE=.\curl.c +SOURCE=.\interface.c # End Source File + +# Begin Source File +SOURCE=.\multi.c +# End Source File + +# Begin Source File +SOURCE=.\streams.c +# End Source File + # End Group # Begin Group "Header Files" diff --git a/ext/curl/curl.c b/ext/curl/interface.c similarity index 92% rename from ext/curl/curl.c rename to ext/curl/interface.c index dd5409b1d0..38992c7e3b 100644 --- a/ext/curl/curl.c +++ b/ext/curl/interface.c @@ -44,8 +44,7 @@ #include "ext/standard/file.h" #include "php_curl.h" -static int le_curl; -#define le_curl_name "cURL handle" +static unsigned char second_arg_force_ref[] = {2, BYREF_NONE, BYREF_FORCE}; static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC); @@ -59,14 +58,22 @@ static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC); /* {{{ curl_functions[] */ function_entry curl_functions[] = { - PHP_FE(curl_init, NULL) - PHP_FE(curl_version, NULL) - PHP_FE(curl_setopt, NULL) - PHP_FE(curl_exec, NULL) - PHP_FE(curl_getinfo, NULL) - PHP_FE(curl_error, NULL) - PHP_FE(curl_errno, NULL) - PHP_FE(curl_close, NULL) + PHP_FE(curl_init, NULL) + PHP_FE(curl_version, NULL) + PHP_FE(curl_setopt, NULL) + PHP_FE(curl_exec, NULL) + PHP_FE(curl_getinfo, NULL) + PHP_FE(curl_error, NULL) + PHP_FE(curl_errno, NULL) + PHP_FE(curl_close, NULL) + PHP_FE(curl_multi_init, NULL) + PHP_FE(curl_multi_add_handle, NULL) + PHP_FE(curl_multi_remove_handle, NULL) + PHP_FE(curl_multi_select, NULL) + PHP_FE(curl_multi_exec, second_arg_force_ref) + PHP_FE(curl_multi_getcontent, NULL) + PHP_FE(curl_multi_info_read, NULL) + PHP_FE(curl_multi_close, NULL) {NULL, NULL, NULL} }; /* }}} */ @@ -109,6 +116,7 @@ PHP_MINFO_FUNCTION(curl) PHP_MINIT_FUNCTION(curl) { le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, "curl", module_number); + le_curl_multi_handle = zend_register_list_destructors_ex(_php_curl_multi_close, NULL, "curl", module_number); /* Constants for curl_setopt() */ REGISTER_CURL_CONSTANT(CURLOPT_DNS_USE_GLOBAL_CACHE); @@ -183,6 +191,9 @@ PHP_MINIT_FUNCTION(curl) REGISTER_CURL_CONSTANT(CURLOPT_COOKIEJAR); REGISTER_CURL_CONSTANT(CURLOPT_SSL_CIPHER_LIST); REGISTER_CURL_CONSTANT(CURLOPT_BINARYTRANSFER); + REGISTER_CURL_CONSTANT(CURLOPT_NOSIGNAL); + REGISTER_CURL_CONSTANT(CURLOPT_PROXYTYPE); + REGISTER_CURL_CONSTANT(CURLOPT_BUFFERSIZE); REGISTER_CURL_CONSTANT(CURLOPT_HTTPGET); REGISTER_CURL_CONSTANT(CURLOPT_HTTP_VERSION); REGISTER_CURL_CONSTANT(CURLOPT_SSLKEY); @@ -221,6 +232,15 @@ PHP_MINIT_FUNCTION(curl) REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_TIME); REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_COUNT); + /* cURL protocol constants (curl_version) */ + REGISTER_CURL_CONSTANT(CURL_VERSION_IPV6); + REGISTER_CURL_CONSTANT(CURL_VERSION_KERBEROS4); + REGISTER_CURL_CONSTANT(CURL_VERSION_SSL); + REGISTER_CURL_CONSTANT(CURL_VERSION_LIBZ); + + /* version constants */ + REGISTER_CURL_CONSTANT(CURLVERSION_NOW); + /* Error Constants */ REGISTER_CURL_CONSTANT(CURLE_OK); REGISTER_CURL_CONSTANT(CURLE_UNSUPPORTED_PROTOCOL); @@ -275,6 +295,9 @@ PHP_MINIT_FUNCTION(curl) REGISTER_CURL_CONSTANT(CURLE_OBSOLETE); REGISTER_CURL_CONSTANT(CURLE_SSL_PEER_CERTIFICATE); + REGISTER_CURL_CONSTANT(CURLPROXY_HTTP); + REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS5); + REGISTER_CURL_CONSTANT(CURL_NETRC_OPTIONAL); REGISTER_CURL_CONSTANT(CURL_NETRC_IGNORED); REGISTER_CURL_CONSTANT(CURL_NETRC_REQUIRED); @@ -283,6 +306,14 @@ PHP_MINIT_FUNCTION(curl) REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_0); REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_1); + REGISTER_CURL_CONSTANT(CURLM_CALL_MULTI_PERFORM); + REGISTER_CURL_CONSTANT(CURLM_OK); + REGISTER_CURL_CONSTANT(CURLM_BAD_HANDLE); + REGISTER_CURL_CONSTANT(CURLM_BAD_EASY_HANDLE); + REGISTER_CURL_CONSTANT(CURLM_OUT_OF_MEMORY); + REGISTER_CURL_CONSTANT(CURLM_INTERNAL_ERROR); + + REGISTER_CURL_CONSTANT(CURLMSG_DONE); if (curl_global_init(CURL_GLOBAL_SSL) != CURLE_OK) { return FAILURE; @@ -315,15 +346,6 @@ PHP_MSHUTDOWN_FUNCTION(curl) } /* }}} */ -#define PHP_CURL_STDOUT 0 -#define PHP_CURL_FILE 1 -#define PHP_CURL_USER 2 -#define PHP_CURL_DIRECT 3 -#define PHP_CURL_RETURN 4 -#define PHP_CURL_ASCII 5 -#define PHP_CURL_BINARY 6 -#define PHP_CURL_IGNORE 7 - /* {{{ curl_write */ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx) @@ -333,6 +355,12 @@ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx) size_t length = size * nmemb; TSRMLS_FETCH(); +#if PHP_CURL_DEBUG + fprintf(stderr, "curl_write() called\n"); + fprintf(stderr, "data = %s, size = %d, nmemb = %d, ctx = %x\n", + data, size, nmemb, ctx); +#endif + switch (t->method) { case PHP_CURL_STDOUT: PUTS(data); @@ -569,15 +597,45 @@ static void curl_free_slist(void **slist) /* }}} */ -/* {{{ proto array curl_version(void) +/* {{{ proto array curl_version([int version]) Return cURL version information. */ PHP_FUNCTION(curl_version) { - if (ZEND_NUM_ARGS() != 0) { - WRONG_PARAM_COUNT; + curl_version_info_data *d; + long uversion = CURLVERSION_NOW; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &uversion) == FAILURE) { + return; + } + + d = curl_version_info(uversion); + if (d == NULL) { + RETURN_FALSE; } - RETURN_STRING(curl_version(), 1); + array_init(return_value); + + CAAL("version_number", d->version_num); + CAAL("age", d->age); + CAAL("features", d->features); + CAAL("ssl_version_number", d->ssl_version_num); + CAAS("version", d->version); + CAAS("host", d->host); + CAAS("ssl_version", d->ssl_version); + CAAS("libz_version", d->libz_version); + /* Add an array of protocols */ + { + char **p = (char **) d->protocols; + zval *protocol_list = NULL; + + MAKE_STD_ZVAL(protocol_list); + array_init(protocol_list); + + while (*p != NULL) { + add_next_index_string(protocol_list, *p++, 1); + } + CAAZ("protocols", protocol_list); + } } /* }}} */ @@ -707,6 +765,9 @@ PHP_FUNCTION(curl_setopt) case CURLOPT_SSL_VERIFYHOST: case CURLOPT_SSL_VERIFYPEER: case CURLOPT_DNS_USE_GLOBAL_CACHE: + case CURLOPT_NOSIGNAL: + case CURLOPT_PROXYTYPE: + case CURLOPT_BUFFERSIZE: case CURLOPT_HTTPGET: case CURLOPT_HTTP_VERSION: case CURLOPT_CRLF: @@ -956,10 +1017,10 @@ PHP_FUNCTION(curl_setopt) } /* }}} */ -/* {{{ cleanup_handle(ch) +/* {{{ _php_curl_cleanup_handle(ch) Cleanup an execution phase */ -static void -cleanup_handle(php_curl *ch) +void +_php_curl_cleanup_handle(php_curl *ch) { if (ch->uses < 1) { return; @@ -988,7 +1049,7 @@ PHP_FUNCTION(curl_exec) } ZEND_FETCH_RESOURCE(ch, php_curl *, zid, -1, le_curl_name, le_curl); - cleanup_handle(ch); + _php_curl_cleanup_handle(ch); error = curl_easy_perform(ch->cp); SAVE_CURL_ERROR(ch, error); @@ -1005,7 +1066,7 @@ PHP_FUNCTION(curl_exec) if (ch->handlers->write->method == PHP_CURL_RETURN && ch->handlers->write->buf.len > 0) { if (ch->handlers->write->type != PHP_CURL_BINARY) smart_str_0(&ch->handlers->write->buf); - RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 1); + RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 0); } RETURN_TRUE; @@ -1182,6 +1243,10 @@ static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC) { php_curl *ch = (php_curl *) rsrc->ptr; +#if PHP_CURL_DEBUG + fprintf(stderr, "DTOR CALLED, ch = %x\n", ch); +#endif + curl_easy_cleanup(ch->cp); zend_llist_clean(&ch->to_free.str); zend_llist_clean(&ch->to_free.slist); diff --git a/ext/curl/multi.c b/ext/curl/multi.c new file mode 100644 index 0000000000..ea9a0af4a7 --- /dev/null +++ b/ext/curl/multi.c @@ -0,0 +1,238 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.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. | + +----------------------------------------------------------------------+ + | Author: Sterling Hughes | + +----------------------------------------------------------------------+ +*/ + +/* $Id: */ + +#include "php.h" + +#if HAVE_CURL + +#include "php_curl.h" + +#include +#include + +#include +#include +#include +#include + +/* {{{ proto resource curl_multi_init(void) + Returns a new cURL multi handle */ +PHP_FUNCTION(curl_multi_init) +{ + php_curlm *mh; + + if (ZEND_NUM_ARGS() != 0) { + WRONG_PARAM_COUNT; + } + + mh = ecalloc(1, sizeof(php_curlm)); + mh->multi = curl_multi_init(); + + ZEND_REGISTER_RESOURCE(return_value, mh, le_curl_multi_handle); +} +/* }}} */ + +/* {{{ int curl_multi_add_handle(resource multi, resource ch) + Add a normal cURL handle to a cURL multi handle */ +PHP_FUNCTION(curl_multi_add_handle) +{ + zval *z_mh; + zval *z_ch; + php_curlm *mh; + php_curl *ch; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &z_mh, &z_ch) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, + le_curl_multi_handle); + ZEND_FETCH_RESOURCE(ch, php_curl *, &z_ch, -1, le_curl_name, le_curl); + + zval_add_ref(&z_ch); + + _php_curl_cleanup_handle(ch); + ch->uses++; + + RETURN_LONG((long) curl_multi_add_handle(mh->multi, ch->cp)); +} +/* }}} */ + +/* {{{ proto int curl_multi_remove_handle(resource mh, resource ch) + Remove a multi handle from a set of cURL handles */ +PHP_FUNCTION(curl_multi_remove_handle) +{ + zval *z_mh; + zval *z_ch; + php_curlm *mh; + php_curl *ch; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &z_mh, &z_ch) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, + le_curl_multi_handle); + ZEND_FETCH_RESOURCE(ch, php_curl *, &z_ch, -1, le_curl_name, le_curl); + + zval_ptr_dtor(&z_ch); + + RETURN_LONG((long) curl_multi_remove_handle(mh->multi, ch->cp)); +} +/* }}} */ + + +static void _make_timeval_struct(struct timeval *to, double timeout) +{ + unsigned long conv; + + conv = (unsigned long) (timeout * 1000000.0); + to->tv_sec = conv / 1000000; + to->tv_usec = conv % 1000000; +} + +/* {{{ int curl_multi_select(resource mh[, double timeout]) + Get all the sockets associated with the cURL extension, which can then be "selected" */ +PHP_FUNCTION(curl_multi_select) +{ + zval *z_mh; + php_curlm *mh; + fd_set readfds; + fd_set writefds; + fd_set exceptfds; + int maxfd; + double timeout = 1.0; + struct timeval to; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|d", &z_mh, + &timeout) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, + le_curl_multi_handle); + + _make_timeval_struct(&to, timeout); + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + + curl_multi_fdset(mh->multi, &readfds, &writefds, &exceptfds, &maxfd); + RETURN_LONG(select(maxfd + 1, &readfds, &writefds, &exceptfds, &to)); +} +/* }}} */ + +/* {{{ proto int curl_multi_exec(resource mh) + Run the sub-connections of the current cURL handle */ +PHP_FUNCTION(curl_multi_exec) +{ + zval *z_mh; + zval *z_still_running; + php_curlm *mh; + int still_running; + int result; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &z_mh, + &z_still_running) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, + le_curl_multi_handle); + + convert_to_long_ex(&z_still_running); + still_running = Z_LVAL_P(z_still_running); + result = curl_multi_perform(mh->multi, &still_running); + ZVAL_LONG(z_still_running, still_running); + + RETURN_LONG(result); +} +/* }}} */ + +/* {{{ proto string curl_multi_getcontent(resource ch) + Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set */ +PHP_FUNCTION(curl_multi_getcontent) +{ + zval *z_ch; + php_curl *ch; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ch) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(ch, php_curl *, &z_ch, -1, le_curl_name, le_curl); + + if (ch->handlers->write->method == PHP_CURL_RETURN && + ch->handlers->write->buf.len > 0) { + if (ch->handlers->write->type == PHP_CURL_BINARY) { + smart_str_0(&ch->handlers->write->buf); + } + + RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 0); + } +} + + +/* {{{ proto array curl_multi_info_read(resource mh) + Get information about the current transfers */ +PHP_FUNCTION(curl_multi_info_read) +{ + zval *z_mh; + php_curlm *mh; + CURLMsg *tmp_msg; + int queued_msgs; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_mh) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, + le_curl_multi_handle); + + tmp_msg = curl_multi_info_read(mh->multi, &queued_msgs); + if (tmp_msg == NULL) { + RETURN_FALSE; + } + + array_init(return_value); + add_assoc_long(return_value, "msg", tmp_msg->msg); + add_assoc_long(return_value, "result", tmp_msg->data.result); +// add_assoc_resource(return_value, "handle", _find_handle(tmp_msg->easy_handle)); + add_assoc_string(return_value, "whatever", (char *) tmp_msg->data.whatever, 1); +} +/* }}} */ + +PHP_FUNCTION(curl_multi_close) +{ + zval *z_mh; + php_curlm *mh; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_mh) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, + le_curl_multi_handle); + + zend_list_delete(Z_LVAL_P(z_mh)); +} + +void _php_curl_multi_close(zend_rsrc_list_entry *rsrc) +{ + php_curlm *mh = (php_curlm *) rsrc->ptr; + curl_multi_cleanup(mh->multi); + // XXX: keep track of all curl handles and zval_ptr_dtor them here +} + +#endif diff --git a/ext/curl/php_curl.h b/ext/curl/php_curl.h index 7881c2f26b..95a4e9c294 100644 --- a/ext/curl/php_curl.h +++ b/ext/curl/php_curl.h @@ -13,7 +13,7 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Sterling Hughes | - | Wez Furlong | + | Wez Furlong | +----------------------------------------------------------------------+ */ @@ -32,14 +32,29 @@ #if HAVE_CURL -#include +#define PHP_CURL_DEBUG 0 +#include +#include extern zend_module_entry curl_module_entry; #define curl_module_ptr &curl_module_entry #define CURLOPT_RETURNTRANSFER 19913 #define CURLOPT_BINARYTRANSFER 19914 +#define PHP_CURL_STDOUT 0 +#define PHP_CURL_FILE 1 +#define PHP_CURL_USER 2 +#define PHP_CURL_DIRECT 3 +#define PHP_CURL_RETURN 4 +#define PHP_CURL_ASCII 5 +#define PHP_CURL_BINARY 6 +#define PHP_CURL_IGNORE 7 + +int le_curl; +#define le_curl_name "cURL handle" +int le_curl_multi_handle; +#define le_curl_multi_handle_name "cURL Multi Handle" PHP_MINIT_FUNCTION(curl); PHP_MSHUTDOWN_FUNCTION(curl); @@ -52,6 +67,15 @@ PHP_FUNCTION(curl_getinfo); PHP_FUNCTION(curl_error); PHP_FUNCTION(curl_errno); PHP_FUNCTION(curl_close); +PHP_FUNCTION(curl_multi_init); +PHP_FUNCTION(curl_multi_add_handle); +PHP_FUNCTION(curl_multi_remove_handle); +PHP_FUNCTION(curl_multi_select); +PHP_FUNCTION(curl_multi_exec); +PHP_FUNCTION(curl_multi_getcontent); +PHP_FUNCTION(curl_multi_info_read); +PHP_FUNCTION(curl_multi_close); +void _php_curl_multi_close(zend_rsrc_list_entry *); typedef struct { zval *func; @@ -87,14 +111,21 @@ struct _php_curl_free { }; typedef struct { - CURL *cp; - php_curl_handlers *handlers; struct _php_curl_error err; struct _php_curl_free to_free; + CURL *cp; + php_curl_handlers *handlers; long id; unsigned int uses; } php_curl; +typedef struct { + int still_running; + CURLM *multi; +} php_curlm; + +void _php_curl_cleanup_handle(php_curl *); + /* streams support */ PHPAPI extern php_stream_ops php_curl_stream_ops; diff --git a/ext/curl/curlstreams.c b/ext/curl/streams.c similarity index 100% rename from ext/curl/curlstreams.c rename to ext/curl/streams.c