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 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
26 #include "php_http_std_defs.h"
27 #include "php_http_requestpool_object.h"
28 #include "php_http_request_pool_api.h"
29 #include "php_http_request_object.h"
30 #include "php_http_exception_object.h"
32 #include "zend_interfaces.h"
35 # include <winsock2.h>
37 #include <curl/curl.h>
39 #define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequestPool, method, 0, req_args)
40 #define HTTP_EMPTY_ARGS(method, ret_ref) HTTP_EMPTY_ARGS_EX(HttpRequestPool, method, ret_ref)
41 #define HTTP_REQPOOL_ME(method, visibility) PHP_ME(HttpRequestPool, method, HTTP_ARGS(HttpRequestPool, method), visibility)
43 HTTP_BEGIN_ARGS_AR(HttpRequestPool
, __construct
, 0, 0)
44 HTTP_ARG_OBJ(HttpRequest
, request0
, 0)
45 HTTP_ARG_OBJ(HttpRequest
, request1
, 0)
46 HTTP_ARG_OBJ(HttpRequest
, requestN
, 0)
49 HTTP_EMPTY_ARGS(__destruct
, 0);
50 HTTP_EMPTY_ARGS(reset
, 0);
52 HTTP_BEGIN_ARGS(attach
, 1)
53 HTTP_ARG_OBJ(HttpRequest
, request
, 0)
56 HTTP_BEGIN_ARGS(detach
, 1)
57 HTTP_ARG_OBJ(HttpRequest
, request
, 0)
60 HTTP_EMPTY_ARGS(send
, 0);
61 HTTP_EMPTY_ARGS(socketPerform
, 0);
62 HTTP_EMPTY_ARGS(socketSelect
, 0);
64 HTTP_EMPTY_ARGS(valid
, 0);
65 HTTP_EMPTY_ARGS(current
, 1);
66 HTTP_EMPTY_ARGS(key
, 0);
67 HTTP_EMPTY_ARGS(next
, 0);
68 HTTP_EMPTY_ARGS(rewind
, 0);
70 #define http_requestpool_object_declare_default_properties() _http_requestpool_object_declare_default_properties(TSRMLS_C)
71 static inline void _http_requestpool_object_declare_default_properties(TSRMLS_D
);
73 zend_class_entry
*http_requestpool_object_ce
;
74 zend_function_entry http_requestpool_object_fe
[] = {
75 HTTP_REQPOOL_ME(__construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
76 HTTP_REQPOOL_ME(__destruct
, ZEND_ACC_PUBLIC
|ZEND_ACC_DTOR
)
77 HTTP_REQPOOL_ME(attach
, ZEND_ACC_PUBLIC
)
78 HTTP_REQPOOL_ME(detach
, ZEND_ACC_PUBLIC
)
79 HTTP_REQPOOL_ME(send
, ZEND_ACC_PUBLIC
)
80 HTTP_REQPOOL_ME(reset
, ZEND_ACC_PUBLIC
)
82 HTTP_REQPOOL_ME(socketPerform
, ZEND_ACC_PROTECTED
)
83 HTTP_REQPOOL_ME(socketSelect
, ZEND_ACC_PROTECTED
)
85 /* implements Interator */
86 HTTP_REQPOOL_ME(valid
, ZEND_ACC_PUBLIC
)
87 HTTP_REQPOOL_ME(current
, ZEND_ACC_PUBLIC
)
88 HTTP_REQPOOL_ME(key
, ZEND_ACC_PUBLIC
)
89 HTTP_REQPOOL_ME(next
, ZEND_ACC_PUBLIC
)
90 HTTP_REQPOOL_ME(rewind
, ZEND_ACC_PUBLIC
)
94 static zend_object_handlers http_requestpool_object_handlers
;
96 void _http_requestpool_object_init(INIT_FUNC_ARGS
)
98 HTTP_REGISTER_CLASS_EX(HttpRequestPool
, http_requestpool_object
, NULL
, 0);
99 zend_class_implements(http_requestpool_object_ce TSRMLS_CC
, 1, zend_ce_iterator
);
102 zend_object_value
_http_requestpool_object_new(zend_class_entry
*ce TSRMLS_DC
)
104 zend_object_value ov
;
105 http_requestpool_object
*o
;
107 o
= ecalloc(1, sizeof(http_requestpool_object
));
110 http_request_pool_init(&o
->pool
);
112 ALLOC_HASHTABLE(OBJ_PROP(o
));
113 zend_hash_init(OBJ_PROP(o
), 0, NULL
, ZVAL_PTR_DTOR
, 0);
114 zend_hash_copy(OBJ_PROP(o
), &ce
->default_properties
, (copy_ctor_func_t
) zval_add_ref
, NULL
, sizeof(zval
*));
116 ov
.handle
= putObject(http_requestpool_object
, o
);
117 ov
.handlers
= &http_requestpool_object_handlers
;
122 static inline void _http_requestpool_object_declare_default_properties(TSRMLS_D
)
124 zend_class_entry
*ce
= http_requestpool_object_ce
;
126 DCL_PROP_N(PROTECTED
, pool
);
129 void _http_requestpool_object_free(zend_object
*object TSRMLS_DC
)
131 http_requestpool_object
*o
= (http_requestpool_object
*) object
;
134 zend_hash_destroy(OBJ_PROP(o
));
135 FREE_HASHTABLE(OBJ_PROP(o
));
137 http_request_pool_dtor(&o
->pool
);
141 /* ### USERLAND ### */
143 /* {{{ proto void HttpRequestPool::__construct([HttpRequest request[, ...]])
145 * Instantiate a new HttpRequestPool object. An HttpRequestPool is
146 * able to send several HttpRequests in parallel.
148 * WARNING: Don't attach/detach HttpRequest objects to the HttpRequestPool
149 * object while you're using the implemented Interator interface.
151 * Accepts virtual infinite optional parameters each referencing an
152 * HttpRequest object.
154 * Throws HttpRequestException, HttpRequestPoolException, HttpInvalidParamException.
160 * $pool = new HttpRequestPool(
161 * new HttpRequest('http://www.google.com/', HttpRequest::METH_HEAD),
162 * new HttpRequest('http://www.php.net/', HttpRequest::METH_HEAD)
165 * foreach($pool as $request) {
166 * printf("%s is %s (%d)\n",
167 * $request->getUrl(),
168 * $request->getResponseCode() ? 'alive' : 'not alive',
169 * $request->getResponseCode()
172 * } catch (HttpException $e) {
178 PHP_METHOD(HttpRequestPool
, __construct
)
180 int argc
= ZEND_NUM_ARGS();
181 zval
***argv
= safe_emalloc(argc
, sizeof(zval
*), 0);
182 getObject(http_requestpool_object
, obj
);
184 if (SUCCESS
== zend_get_parameters_array_ex(argc
, argv
)) {
187 for (i
= 0; i
< argc
; ++i
) {
188 if (Z_TYPE_PP(argv
[i
]) == IS_OBJECT
&& instanceof_function(Z_OBJCE_PP(argv
[i
]), http_request_object_ce TSRMLS_CC
)) {
189 http_request_pool_attach(&obj
->pool
, *(argv
[i
]));
197 /* {{{ proto void HttpRequestPool::__destruct()
199 * Clean up HttpRequestPool object.
201 PHP_METHOD(HttpRequestPool
, __destruct
)
203 getObject(http_requestpool_object
, obj
);
207 http_request_pool_detach_all(&obj
->pool
);
211 /* {{{ proto void HttpRequestPool::reset()
213 * Detach all attached HttpRequest objects.
215 PHP_METHOD(HttpRequestPool
, reset
)
217 getObject(http_requestpool_object
, obj
);
221 http_request_pool_detach_all(&obj
->pool
);
224 /* {{{ proto bool HttpRequestPool::attach(HttpRequest request)
226 * Attach an HttpRequest object to this HttpRequestPool.
227 * WARNING: set all options prior attaching!
229 * Expects the parameter to be an HttpRequest object not alread attached to
230 * antother HttpRequestPool object.
232 * Returns TRUE on success, or FALSE on failure.
234 * Throws HttpInvalidParamException, HttpRequestException,
235 * HttpRequestPoolException, HttpEncodingException.
237 PHP_METHOD(HttpRequestPool
, attach
)
240 STATUS status
= FAILURE
;
241 getObject(http_requestpool_object
, obj
);
244 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O", &request
, http_request_object_ce
)) {
245 status
= http_request_pool_attach(&obj
->pool
, request
);
248 RETURN_SUCCESS(status
);
252 /* {{{ proto bool HttpRequestPool::detach(HttpRequest request)
254 * Detach an HttpRequest object from this HttpRequestPool.
256 * Expects the parameter to be an HttpRequest object attached to this
257 * HttpRequestPool object.
259 * Returns TRUE on success, or FALSE on failure.
261 * Throws HttpInvalidParamException, HttpRequestPoolException.
263 PHP_METHOD(HttpRequestPool
, detach
)
266 STATUS status
= FAILURE
;
267 getObject(http_requestpool_object
, obj
);
270 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O", &request
, http_request_object_ce
)) {
271 status
= http_request_pool_detach(&obj
->pool
, request
);
274 RETURN_SUCCESS(status
);
278 /* {{{ proto bool HttpRequestPool::send()
280 * Send all attached HttpRequest objects in parallel.
282 * Returns TRUE on success, or FALSE on failure.
284 * Throws HttpSocketException, HttpRequestException,
285 * HttpRequestPoolException, HttpMalformedHeaderException.
287 PHP_METHOD(HttpRequestPool
, send
)
290 getObject(http_requestpool_object
, obj
);
295 status
= http_request_pool_send(&obj
->pool
);
298 RETURN_SUCCESS(status
);
302 /* {{{ proto protected bool HttpRequestPool::socketPerform()
304 * Returns TRUE until each request has finished its transaction.
309 * while ($pool->socketPerform()) {
310 * do_something_else();
311 * if (!$pool->socketSelect()) {
312 * die('Socket error');
318 PHP_METHOD(HttpRequestPool
, socketPerform
)
320 getObject(http_requestpool_object
, obj
);
324 if (0 < http_request_pool_perform(&obj
->pool
)) {
327 zend_llist_apply(&obj
->pool
.handles
, (llist_apply_func_t
) http_request_pool_responsehandler TSRMLS_CC
);
333 /* {{{ proto protected bool HttpRequestPool::socketSelect()
335 * See HttpRequestPool::socketPerform().
337 * Returns TRUE on success, or FALSE on failure.
339 PHP_METHOD(HttpRequestPool
, socketSelect
)
341 getObject(http_requestpool_object
, obj
);
345 RETURN_SUCCESS(http_request_pool_select(&obj
->pool
));
349 /* implements Iterator */
351 /* {{{ proto bool HttpRequestPool::valid()
353 * Implements Iterator::valid().
355 PHP_METHOD(HttpRequestPool
, valid
)
360 getObject(http_requestpool_object
, obj
);
361 RETURN_BOOL(obj
->iterator
.pos
< zend_llist_count(&obj
->pool
.handles
));
366 /* {{{ proto HttpRequest HttpRequestPool::current()
368 * Implements Iterator::current().
370 PHP_METHOD(HttpRequestPool
, current
)
376 zval
**current
= NULL
;
377 zend_llist_position lpos
;
378 getObject(http_requestpool_object
, obj
);
380 if (obj
->iterator
.pos
< zend_llist_count(&obj
->pool
.handles
)) {
381 for ( current
= zend_llist_get_first_ex(&obj
->pool
.handles
, &lpos
);
382 current
&& obj
->iterator
.pos
!= pos
++;
383 current
= zend_llist_get_next_ex(&obj
->pool
.handles
, &lpos
));
385 RETURN_OBJECT(*current
);
393 /* {{{ proto int HttpRequestPool::key()
395 * Implements Iterator::key().
397 PHP_METHOD(HttpRequestPool
, key
)
402 getObject(http_requestpool_object
, obj
);
403 RETURN_LONG(obj
->iterator
.pos
);
408 /* {{{ proto void HttpRequestPool::next()
410 * Implements Iterator::next().
412 PHP_METHOD(HttpRequestPool
, next
)
415 getObject(http_requestpool_object
, obj
);
416 ++(obj
->iterator
.pos
);
421 /* {{{ proto void HttpRequestPool::rewind()
423 * Implements Iterator::rewind().
425 PHP_METHOD(HttpRequestPool
, rewind
)
428 getObject(http_requestpool_object
, obj
);
429 obj
->iterator
.pos
= 0;
434 #endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
441 * vim600: noet sw=4 ts=4 fdm=marker
442 * vim<600: noet sw=4 ts=4