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 +----------------------------------------------------------------------+
23 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
26 #include "php_http_std_defs.h"
27 #include "php_http_api.h"
28 #include "php_http_request_api.h"
29 #include "php_http_request_pool_api.h"
30 #include "php_http_request_object.h"
31 #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");
63 zend_llist_init(&pool
->handles
, sizeof(zval
*), (llist_dtor_func_t
) ZVAL_PTR_DTOR
, 0);
64 zend_llist_init(&pool
->bodies
, sizeof(http_request_body
*), (llist_dtor_func_t
) http_request_pool_freebody
, 0);
65 #if HTTP_DEBUG_REQPOOLS
66 fprintf(stderr
, "Initialized request pool %p\n", pool
);
72 /* {{{ STATUS http_request_pool_attach(http_request_pool *, zval *) */
73 PHP_HTTP_API STATUS
_http_request_pool_attach(http_request_pool
*pool
, zval
*request TSRMLS_DC
)
75 getObjectEx(http_request_object
, req
, request
);
76 #if HTTP_DEBUG_REQPOOLS
77 fprintf(stderr
, "Attaching request %p to pool %p\n", req
, pool
);
80 http_error(E_WARNING
, HTTP_E_CURL
, "HttpRequest object is already member of an HttpRequestPool");
83 http_request_body
*body
= http_request_body_new();
84 zval
*info
= GET_PROP_EX(req
, request
, responseInfo
);
86 if (SUCCESS
!= http_request_object_requesthandler(req
, request
, body
)) {
87 http_error_ex(E_WARNING
, HTTP_E_CURL
, "Could not initialize HttpRequest object for attaching to the HttpRequestPool");
89 code
= curl_multi_add_handle(pool
->ch
, req
->ch
);
90 if ((CURLM_OK
!= code
) && (CURLM_CALL_MULTI_PERFORM
!= code
)) {
91 http_error_ex(E_WARNING
, HTTP_E_CURL
, "Could not attach HttpRequest object to the HttpRequestPool: %s", curl_multi_strerror(code
));
94 zend_llist_add_element(&pool
->handles
, &request
);
95 zend_llist_add_element(&pool
->bodies
, &body
);
96 zval_add_ref(&request
);
106 /* {{{ STATUS http_request_pool_detach(http_request_pool *, zval *) */
107 PHP_HTTP_API STATUS
_http_request_pool_detach(http_request_pool
*pool
, zval
*request TSRMLS_DC
)
109 getObjectEx(http_request_object
, req
, request
);
110 #if HTTP_DEBUG_REQPOOLS
111 fprintf(stderr
, "Detaching request %p from pool %p\n", req
, pool
);
113 if (req
->pool
!= pool
) {
114 http_error(E_WARNING
, HTTP_E_CURL
, "HttpRequest object is not attached to this HttpRequestPool");
118 if (CURLM_OK
!= (code
= curl_multi_remove_handle(pool
->ch
, req
->ch
))) {
119 http_error_ex(E_WARNING
, HTTP_E_CURL
, "Could not detach HttpRequest object from the HttpRequestPool: %s", curl_multi_strerror(code
));
122 zend_llist_del_element(&pool
->handles
, request
, http_request_pool_compare_handles
);
130 /* {{{ void http_request_pool_detach_all(http_request_pool *) */
131 PHP_HTTP_API
void _http_request_pool_detach_all(http_request_pool
*pool TSRMLS_DC
)
133 int count
= zend_llist_count(&pool
->handles
);
134 #if HTTP_DEBUG_REQPOOLS
135 fprintf(stderr
, "Detaching %d requests from pool %p\n", count
, pool
);
138 * we cannot apply a function to the llist which actually detaches
139 * the curl handle *and* removes the llist element --
140 * so let's get our hands dirty
144 zend_llist_position pos
;
145 zval
**handle
, **handles
= emalloc(count
* sizeof(zval
*));
147 for (handle
= zend_llist_get_first_ex(&pool
->handles
, &pos
); handle
; handle
= zend_llist_get_next_ex(&pool
->handles
, &pos
)) {
148 handles
[i
++] = *handle
;
150 for (i
= 0; i
< count
; ++i
) {
151 http_request_pool_detach(pool
, handles
[i
]);
158 /* {{{ STATUS http_request_pool_send(http_request_pool *) */
159 PHP_HTTP_API STATUS
_http_request_pool_send(http_request_pool
*pool TSRMLS_DC
)
161 #if HTTP_DEBUG_REQPOOLS
162 fprintf(stderr
, "Attempt to send %d requests of pool %p\n", zend_llist_count(&pool
->handles
), pool
);
164 while (http_request_pool_perform(pool
)) {
165 #if HTTP_DEBUG_REQPOOLS
166 fprintf(stderr
, "%d unfinished requests of pool %p remaining\n", pool
->unfinished
, pool
);
168 if (SUCCESS
!= http_request_pool_select(pool
)) {
169 http_error(E_WARNING
, HTTP_E_CURL
, "Socket error");
173 zend_llist_apply(&pool
->handles
, (llist_apply_func_t
) http_request_pool_responsehandler TSRMLS_CC
);
178 /* {{{ void http_request_pool_dtor(http_request_pool *) */
179 PHP_HTTP_API
void _http_request_pool_dtor(http_request_pool
*pool TSRMLS_DC
)
181 #if HTTP_DEBUG_REQPOOLS
182 fprintf(stderr
, "Destructing request pool %p\n", pool
);
184 pool
->unfinished
= 0;
185 zend_llist_clean(&pool
->handles
);
186 zend_llist_clean(&pool
->bodies
);
187 curl_multi_cleanup(pool
->ch
);
191 /* {{{ STATUS http_request_pool_select(http_request_pool *) */
192 PHP_HTTP_API STATUS
_http_request_pool_select(http_request_pool
*pool
)
196 struct timeval timeout
= {1, 0};
202 curl_multi_fdset(pool
->ch
, &R
, &W
, &E
, &MAX
);
203 return (-1 != select(MAX
+ 1, &R
, &W
, &E
, &timeout
)) ? SUCCESS
: FAILURE
;
207 /* {{{ int http_request_pool_perform(http_request_pool *) */
208 PHP_HTTP_API
int _http_request_pool_perform(http_request_pool
*pool
)
210 while (CURLM_CALL_MULTI_PERFORM
== curl_multi_perform(pool
->ch
, &pool
->unfinished
));
211 return pool
->unfinished
;
215 /* {{{ void http_request_pool_responsehandler(zval **) */
216 void _http_request_pool_responsehandler(zval
**req TSRMLS_DC
)
218 getObjectEx(http_request_object
, obj
, *req
);
219 #if HTTP_DEBUG_REQPOOLS
220 fprintf(stderr
, "Fetching data from request %p of pool %p\n", obj
, obj
->pool
);
222 http_request_object_responsehandler(obj
, *req
);
228 /* {{{ static void http_request_pool_freebody(http_request_body **) */
229 static void http_request_pool_freebody(http_request_body
**body
)
232 http_request_body_free(*body
);
236 /* {{{ static int http_request_pool_compare_handles(void *, void *) */
237 static int http_request_pool_compare_handles(void *h1
, void *h2
)
239 return ((*((zval
**) h1
)) == ((zval
*) h2
));
243 #endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
251 * vim600: noet sw=4 ts=4 fdm=marker
252 * vim<600: noet sw=4 ts=4