2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.0 of the PHP license, that |
6 | is bundled with this package in the file LICENSE, and is available |
7 | through the world-wide-web at http://www.php.net/license/3_0.txt. |
8 | If you did not receive a copy of the PHP license and are unable to |
9 | obtain it through the world-wide-web, please send a note to |
10 | license@php.net so we can mail you a copy immediately. |
11 +----------------------------------------------------------------------+
12 | Copyright (c) 2004-2005 Michael Wallner <mike@php.net> |
13 +----------------------------------------------------------------------+
24 #include "php_http_std_defs.h"
25 #include "php_http_api.h"
26 #include "php_http_request_api.h"
27 #include "php_http_request_pool_api.h"
28 #include "php_http_request_object.h"
29 #include "php_http_requestpool_object.h"
33 #ifndef HTTP_DEBUG_REQPOOLS
34 # define HTTP_DEBUG_REQPOOLS 0
37 static void http_request_pool_freebody(http_request_body
**body
);
38 static int http_request_pool_compare_handles(void *h1
, void *h2
);
40 /* {{{ http_request_pool *http_request_pool_init(http_request_pool *) */
41 PHP_HTTP_API http_request_pool
*_http_request_pool_init(http_request_pool
*pool TSRMLS_DC
)
44 #if HTTP_DEBUG_REQPOOLS
45 fprintf(stderr
, "Initializing request pool\n");
47 if ((free_pool
= (!pool
))) {
48 pool
= emalloc(sizeof(http_request_pool
));
53 if (!(pool
->ch
= curl_multi_init())) {
54 http_error(E_WARNING
, HTTP_E_CURL
, "Could not initialize curl");
64 zend_llist_init(&pool
->handles
, sizeof(zval
*), (llist_dtor_func_t
) ZVAL_PTR_DTOR
, 0);
65 zend_llist_init(&pool
->bodies
, sizeof(http_request_body
*), (llist_dtor_func_t
) http_request_pool_freebody
, 0);
66 #if HTTP_DEBUG_REQPOOLS
67 fprintf(stderr
, "Initialized request pool %p\n", pool
);
73 /* {{{ STATUS http_request_pool_attach(http_request_pool *, zval *) */
74 PHP_HTTP_API STATUS
_http_request_pool_attach(http_request_pool
*pool
, zval
*request TSRMLS_DC
)
76 getObjectEx(http_request_object
, req
, request
);
77 #if HTTP_DEBUG_REQPOOLS
78 fprintf(stderr
, "Attaching request %p to pool %p\n", req
, pool
);
81 http_error(E_WARNING
, HTTP_E_CURL
, "HttpRequest object is already member of an HttpRequestPool");
84 http_request_body
*body
= http_request_body_new();
85 zval
*info
= GET_PROP_EX(req
, request
, responseInfo
);
87 if (SUCCESS
!= http_request_object_requesthandler(req
, request
, body
)) {
88 http_error_ex(E_WARNING
, HTTP_E_CURL
, "Could not initialize HttpRequest object for attaching to the HttpRequestPool");
90 code
= curl_multi_add_handle(pool
->ch
, req
->ch
);
91 if ((CURLM_OK
!= code
) && (CURLM_CALL_MULTI_PERFORM
!= code
)) {
92 http_error_ex(E_WARNING
, HTTP_E_CURL
, "Could not attach HttpRequest object to the HttpRequestPool: %s", curl_multi_strerror(code
));
95 zend_llist_add_element(&pool
->handles
, &request
);
96 zend_llist_add_element(&pool
->bodies
, &body
);
97 zval_add_ref(&request
);
107 /* {{{ STATUS http_request_pool_detach(http_request_pool *, zval *) */
108 PHP_HTTP_API STATUS
_http_request_pool_detach(http_request_pool
*pool
, zval
*request TSRMLS_DC
)
110 getObjectEx(http_request_object
, req
, request
);
111 #if HTTP_DEBUG_REQPOOLS
112 fprintf(stderr
, "Detaching request %p from pool %p\n", req
, pool
);
114 if (req
->pool
!= pool
) {
115 http_error(E_WARNING
, HTTP_E_CURL
, "HttpRequest object is not attached to this HttpRequestPool");
119 if (CURLM_OK
!= (code
= curl_multi_remove_handle(pool
->ch
, req
->ch
))) {
120 http_error_ex(E_WARNING
, HTTP_E_CURL
, "Could not detach HttpRequest object from the HttpRequestPool: %s", curl_multi_strerror(code
));
123 zend_llist_del_element(&pool
->handles
, request
, http_request_pool_compare_handles
);
131 /* {{{ void http_request_pool_detach_all(http_request_pool *) */
132 PHP_HTTP_API
void _http_request_pool_detach_all(http_request_pool
*pool TSRMLS_DC
)
134 int count
= zend_llist_count(&pool
->handles
);
135 #if HTTP_DEBUG_REQPOOLS
136 fprintf(stderr
, "Detaching %d requests from pool %p\n", count
, pool
);
139 * we cannot apply a function to the llist which actually detaches
140 * the curl handle *and* removes the llist element --
141 * so let's get our hands dirty
145 zend_llist_position pos
;
146 zval
**handle
, **handles
= emalloc(count
* sizeof(zval
*));
148 for (handle
= zend_llist_get_first_ex(&pool
->handles
, &pos
); handle
; handle
= zend_llist_get_next_ex(&pool
->handles
, &pos
)) {
149 handles
[i
++] = *handle
;
151 for (i
= 0; i
< count
; ++i
) {
152 http_request_pool_detach(pool
, handles
[i
]);
159 /* {{{ STATUS http_request_pool_send(http_request_pool *) */
160 PHP_HTTP_API STATUS
_http_request_pool_send(http_request_pool
*pool TSRMLS_DC
)
162 #if HTTP_DEBUG_REQPOOLS
163 fprintf(stderr
, "Attempt to send requests of pool %p\n", pool
);
166 http_error(E_WARNING
, HTTP_E_CURL
, "HttpRequestPools can only be used once");
171 while (http_request_pool_perform(pool
)) {
172 #if HTTP_DEBUG_REQPOOLS
173 fprintf(stderr
, "%d unfinished requests of pool %p remaining\n", pool
->unfinished
, pool
);
175 if (SUCCESS
!= http_request_pool_select(pool
)) {
176 http_error(E_WARNING
, HTTP_E_CURL
, "Socket error");
180 zend_llist_apply(&pool
->handles
, (llist_apply_func_t
) http_request_pool_responsehandler TSRMLS_CC
);
185 /* {{{ void http_request_pool_dtor(http_request_pool *) */
186 PHP_HTTP_API
void _http_request_pool_dtor(http_request_pool
*pool TSRMLS_DC
)
188 #if HTTP_DEBUG_REQPOOLS
189 fprintf(stderr
, "Destructing request pool %p\n", pool
);
191 pool
->unfinished
= 0;
192 zend_llist_clean(&pool
->handles
);
193 zend_llist_clean(&pool
->bodies
);
194 curl_multi_cleanup(pool
->ch
);
198 /* {{{ STATUS http_request_pool_select(http_request_pool *) */
199 PHP_HTTP_API STATUS
_http_request_pool_select(http_request_pool
*pool
)
203 struct timeval timeout
= {1, 0};
209 curl_multi_fdset(pool
->ch
, &R
, &W
, &E
, &MAX
);
210 return (-1 != select(MAX
+ 1, &R
, &W
, &E
, &timeout
)) ? SUCCESS
: FAILURE
;
214 /* {{{ int http_request_pool_perform(http_request_pool *) */
215 PHP_HTTP_API
int _http_request_pool_perform(http_request_pool
*pool
)
217 while (CURLM_CALL_MULTI_PERFORM
== curl_multi_perform(pool
->ch
, &pool
->unfinished
));
218 return pool
->unfinished
;
222 /* {{{ void http_request_pool_responsehandler(zval **) */
223 void _http_request_pool_responsehandler(zval
**req TSRMLS_DC
)
225 getObjectEx(http_request_object
, obj
, *req
);
226 #if HTTP_DEBUG_REQPOOLS
227 fprintf(stderr
, "Fetching data from request %p of pool %p\n", obj
, obj
->pool
);
229 http_request_object_responsehandler(obj
, *req
);
235 /* {{{ static void http_request_pool_freebody(http_request_body **) */
236 static void http_request_pool_freebody(http_request_body
**body
)
239 http_request_body_free(*body
);
243 /* {{{ static int http_request_pool_compare_handles(void *, void *) */
244 static int http_request_pool_compare_handles(void *h1
, void *h2
)
246 return ((*((zval
**) h1
)) == ((zval
*) h2
));
250 #endif /* ZEND_ENGINE_2 */
258 * vim600: noet sw=4 ts=4 fdm=marker
259 * vim<600: noet sw=4 ts=4