From 82e177a071d35372367f9f5255b3e2c553c8bffd Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Sun, 10 Sep 2006 13:07:01 +0000 Subject: [PATCH] - separate sleeping functionality to _http_sleep() - use curl suggested select timeout - sleep if there are no fds ready for select - add some missing request options --- config9.m4 | 4 ++++ http_request_api.c | 45 +++++++++++++++++++++++++++++++++++++++++ http_request_pool_api.c | 13 +++++++++++- http_send_api.c | 22 +------------------- package2.xml | 2 ++ php_http_api.h | 35 ++++++++++++++++++++++++++++++++ 6 files changed, 99 insertions(+), 22 deletions(-) diff --git a/config9.m4 b/config9.m4 index 1fcb91d..cb7db94 100644 --- a/config9.m4 +++ b/config9.m4 @@ -242,6 +242,10 @@ dnl ---- [AC_DEFINE([HAVE_CURL_MULTI_SETOPT], [1], [ ])], [ ], [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR] ) + PHP_CHECK_LIBRARY(curl, curl_multi_timeout, + [AC_DEFINE([HAVE_CURL_MULTI_TIMEOUT], [1], [ ])], [ ], + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR] + ) fi dnl ---- diff --git a/http_request_api.c b/http_request_api.c index b253a97..9697f6d 100644 --- a/http_request_api.c +++ b/http_request_api.c @@ -347,6 +347,17 @@ PHP_HTTP_API void _http_request_defaults(http_request *request) HTTP_CURL_OPT(CURLOPT_PROXYTYPE, 0L); HTTP_CURL_OPT(CURLOPT_PROXYUSERPWD, NULL); HTTP_CURL_OPT(CURLOPT_PROXYAUTH, 0L); + HTTP_CURL_OPT(CURLOPT_DNS_CACHE_TIMEOUT, 60L); + HTTP_CURL_OPT(CURLOPT_LOW_SPEED_LIMIT, 0L); + HTTP_CURL_OPT(CURLOPT_LOW_SPEED_TIME, 0L); +#if HTTP_CURL_VERSION(7,15,5) + HTTP_CURL_OPT(CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) 0); + HTTP_CURL_OPT(CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) 0); +#endif + /* crashes + HTTP_CURL_OPT(CURLOPT_MAXCONNECTS, 5L); */ + HTTP_CURL_OPT(CURLOPT_FRESH_CONNECT, 0L); + HTTP_CURL_OPT(CURLOPT_FORBID_REUSE, 0L); HTTP_CURL_OPT(CURLOPT_INTERFACE, NULL); HTTP_CURL_OPT(CURLOPT_PORT, 0L); #if HTTP_CURL_VERSION(7,15,2) @@ -461,6 +472,37 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti } } + /* dns */ + if ((zoption = http_request_option(request, options, "dns_cache_timeout", IS_LONG))) { + HTTP_CURL_OPT(CURLOPT_DNS_CACHE_TIMEOUT, Z_LVAL_P(zoption)); + } + + /* limits */ + if ((zoption = http_request_option(request, options, "low_speed_limit", IS_LONG))) { + HTTP_CURL_OPT(CURLOPT_LOW_SPEED_LIMIT, Z_LVAL_P(zoption)); + } + if ((zoption = http_request_option(request, options, "low_speed_time", IS_LONG))) { + HTTP_CURL_OPT(CURLOPT_LOW_SPEED_TIME, Z_LVAL_P(zoption)); + } +#if HTTP_CURL_VERSION(7,15,5) + if ((zoption = http_request_option(request, options, "max_send_speed", IS_LONG))) { + HTTP_CURL_OPT(CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) Z_LVAL_P(zoption)); + } + if ((zoption = http_request_option(request, options, "max_recv_speed", IS_LONG))) { + HTTP_CURL_OPT(CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) Z_LVAL_P(zoption)); + } +#endif + /* crashes + if ((zoption = http_request_option(request, options, "maxconnects", IS_LONG))) { + HTTP_CURL_OPT(CURLOPT_MAXCONNECTS, Z_LVAL_P(zoption)); + } */ + if ((zoption = http_request_option(request, options, "fresh_connect", IS_BOOL)) && Z_BVAL_P(zoption)) { + HTTP_CURL_OPT(CURLOPT_FRESH_CONNECT, 1L); + } + if ((zoption = http_request_option(request, options, "forbid_reuse", IS_BOOL)) && Z_BVAL_P(zoption)) { + HTTP_CURL_OPT(CURLOPT_FORBID_REUSE, 1L); + } + /* outgoing interface */ if ((zoption = http_request_option(request, options, "interface", IS_STRING))) { HTTP_CURL_OPT(CURLOPT_INTERFACE, Z_STRVAL_P(zoption)); @@ -978,6 +1020,9 @@ static int http_curl_raw_callback(CURL *ch, curl_infotype type, char *data, size if (data[length-1] != 0xa) { fprintf(stderr, "\n"); } +#endif +#if 0 + fprintf(stderr, "%.*s%s", length, data, data[length-1]=='\n'?"":"\n"); #endif break; } diff --git a/http_request_pool_api.c b/http_request_pool_api.c index 5b04472..dab929e 100644 --- a/http_request_pool_api.c +++ b/http_request_pool_api.c @@ -261,13 +261,24 @@ PHP_HTTP_API STATUS _http_request_pool_select(http_request_pool *pool) int MAX; fd_set R, W, E; struct timeval timeout = {1, 0}; +#ifdef HAVE_CURL_MULTI_TIMEOUT + long max_tout = 1000; + + if (CURLM_OK == curl_multi_timeout(pool->ch, &max_tout)) { + timeout.tv_sec = max_tout / 1000; + timeout.tv_usec = (max_tout % 1000) * 1000; + } +#endif FD_ZERO(&R); FD_ZERO(&W); FD_ZERO(&E); if (CURLM_OK == curl_multi_fdset(pool->ch, &R, &W, &E, &MAX)) { - if (MAX == -1 || SELECT_ERROR != select(MAX + 1, &R, &W, &E, &timeout)) { + if (MAX == -1) { + http_sleep((double) timeout.tv_sec + (double) (timeout.tv_usec / HTTP_MCROSEC)); + return SUCCESS; + } else if (SELECT_ERROR != select(MAX + 1, &R, &W, &E, &timeout)) { return SUCCESS; } } diff --git a/http_send_api.c b/http_send_api.c index ebecb33..0c1fe57 100644 --- a/http_send_api.c +++ b/http_send_api.c @@ -39,28 +39,8 @@ static inline void _http_flush(void *nothing, const char *data, size_t data_len fprintf(stderr, "Flushing after writing %u bytes\n", (uint) data_len); #endif -#define HTTP_MSEC(s) (s * 1000) -#define HTTP_USEC(s) (HTTP_MSEC(s) * 1000) -#define HTTP_NSEC(s) (HTTP_USEC(s) * 1000) -#define HTTP_NANOSEC (1000 * 1000 * 1000) -#define HTTP_DIFFSEC (0.001) - if (HTTP_G->send.throttle_delay >= HTTP_DIFFSEC) { -#if defined(PHP_WIN32) - Sleep((DWORD) HTTP_MSEC(HTTP_G->send.throttle_delay)); -#elif defined(HAVE_USLEEP) - usleep(HTTP_USEC(HTTP_G->send.throttle_delay)); -#elif defined(HAVE_NANOSLEEP) - struct timespec req, rem; - - req.tv_sec = (time_t) HTTP_G->send.throttle_delay; - req.tv_nsec = HTTP_NSEC(HTTP_G->send.throttle_delay) % HTTP_NANOSEC; - - while (nanosleep(&req, &rem) && (errno == EINTR) && (HTTP_NSEC(rem.tv_sec) + rem.tv_nsec) > HTTP_NSEC(HTTP_DIFFSEC))) { - req.tv_sec = rem.tv_sec; - req.tv_nsec = rem.tv_nsec; - } -#endif + http_sleep(HTTP_G->send.throttle_delay); } } /* }}} */ diff --git a/package2.xml b/package2.xml index 15cfea5..43d6afa 100644 --- a/package2.xml +++ b/package2.xml @@ -40,6 +40,8 @@ support. Parallel requests are available for PHP 5 and greater. BSD, revised = 7.16.0) ++ Added "dns_cache_timeout", "low_speed_limit", "low_speed_time", "max_send_speed", + "max_recv_speed", "forbid_reuse" and "fresh_connect" request options ]]> diff --git a/php_http_api.h b/php_http_api.h index 9e5c389..052fb1e 100644 --- a/php_http_api.h +++ b/php_http_api.h @@ -156,6 +156,41 @@ PHP_HTTP_API void _http_parse_params_default_callback(void *ht, const char *key, PHP_HTTP_API STATUS _http_parse_params_ex(const char *params, int flags, http_parse_params_callback cb, void *cb_arg TSRMLS_DC); +#define http_sleep(s) _http_sleep(s) +static inline void _http_sleep(double s) +{ +#define HTTP_DIFFSEC (0.001) +#define HTTP_MLLISEC (1000) +#define HTTP_MCROSEC (1000 * 1000) +#define HTTP_NANOSEC (1000 * 1000 * 1000) +#define HTTP_MSEC(s) (s * HTTP_MLLISEC) +#define HTTP_USEC(s) (s * HTTP_MCROSEC) +#define HTTP_NSEC(s) (s * HTTP_NANOSEC) + +#if defined(PHP_WIN32) + Sleep((DWORD) HTTP_MSEC(s)); +#elif defined(HAVE_USLEEP) + usleep(HTTP_USEC(s)); +#elif defined(HAVE_NANOSLEEP) + struct timespec req, rem; + + req.tv_sec = (time_t) s; + req.tv_nsec = HTTP_NSEC(s) % HTTP_NANOSEC; + + while (nanosleep(&req, &rem) && (errno == EINTR) && (HTTP_NSEC(rem.tv_sec) + rem.tv_nsec) > HTTP_NSEC(HTTP_DIFFSEC))) { + req.tv_sec = rem.tv_sec; + req.tv_nsec = rem.tv_nsec; + } +#else + struct timeval timeout; + + timeout.tv.sec = (time_t) s; + timeout.tv_usec = HTTP_USEC(s) % HTTP_MCROSEC; + + select(0, NULL, NULL, NULL, &timeout); +#endif +} + #define http_locate_body _http_locate_body static inline const char *_http_locate_body(const char *message) { -- 2.30.2