- separate http_methods.c into http_*_object.c files
[m6w6/ext-http] / http_requestpool_object.c
1 /*
2 +----------------------------------------------------------------------+
3 | PECL :: http |
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 +----------------------------------------------------------------------+
14 */
15
16 /* $Id$ */
17
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22 #include "php.h"
23
24 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
25
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"
31
32 #ifdef PHP_WIN32
33 # include <winsock2.h>
34 #endif
35 #include <curl/curl.h>
36
37 #define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequestPool, method, ZEND_RETURN_REFERENCE_AGNOSTIC, req_args)
38 #define HTTP_EMPTY_ARGS(method, ret_ref) HTTP_EMPTY_ARGS_EX(HttpRequestPool, method, ret_ref)
39 #define HTTP_REQPOOL_ME(method, visibility) PHP_ME(HttpRequestPool, method, HTTP_ARGS(HttpRequestPool, method), visibility)
40
41 HTTP_BEGIN_ARGS_AR(HttpRequestPool, __construct, 0, 0)
42 HTTP_ARG_OBJ(HttpRequest, request0, 0)
43 HTTP_ARG_OBJ(HttpRequest, request1, 0)
44 HTTP_ARG_OBJ(HttpRequest, requestN, 0)
45 HTTP_END_ARGS;
46
47 HTTP_EMPTY_ARGS(__destruct, 0);
48 HTTP_EMPTY_ARGS(reset, 0);
49
50 HTTP_BEGIN_ARGS(attach, 1)
51 HTTP_ARG_OBJ(HttpRequest, request, 0)
52 HTTP_END_ARGS;
53
54 HTTP_BEGIN_ARGS(detach, 1)
55 HTTP_ARG_OBJ(HttpRequest, request, 0)
56 HTTP_END_ARGS;
57
58 HTTP_EMPTY_ARGS(send, 0);
59 HTTP_EMPTY_ARGS(socketSend, 0);
60 HTTP_EMPTY_ARGS(socketSelect, 0);
61 HTTP_EMPTY_ARGS(socketRead, 0);
62
63
64 #define http_requestpool_object_declare_default_properties() _http_requestpool_object_declare_default_properties(TSRMLS_C)
65 static inline void _http_requestpool_object_declare_default_properties(TSRMLS_D);
66
67 zend_class_entry *http_requestpool_object_ce;
68 zend_function_entry http_requestpool_object_fe[] = {
69 HTTP_REQPOOL_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
70 HTTP_REQPOOL_ME(__destruct, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
71 HTTP_REQPOOL_ME(attach, ZEND_ACC_PUBLIC)
72 HTTP_REQPOOL_ME(detach, ZEND_ACC_PUBLIC)
73 HTTP_REQPOOL_ME(send, ZEND_ACC_PUBLIC)
74 HTTP_REQPOOL_ME(reset, ZEND_ACC_PUBLIC)
75
76 HTTP_REQPOOL_ME(socketSend, ZEND_ACC_PROTECTED)
77 HTTP_REQPOOL_ME(socketSelect, ZEND_ACC_PROTECTED)
78 HTTP_REQPOOL_ME(socketRead, ZEND_ACC_PROTECTED)
79
80 {NULL, NULL, NULL}
81 };
82 static zend_object_handlers http_requestpool_object_handlers;
83
84 void _http_requestpool_object_init(INIT_FUNC_ARGS)
85 {
86 HTTP_REGISTER_CLASS_EX(HttpRequestPool, http_requestpool_object, NULL, 0);
87 }
88
89 zend_object_value _http_requestpool_object_new(zend_class_entry *ce TSRMLS_DC)
90 {
91 zend_object_value ov;
92 http_requestpool_object *o;
93
94 o = ecalloc(1, sizeof(http_requestpool_object));
95 o->zo.ce = ce;
96
97 http_request_pool_init(&o->pool);
98
99 ALLOC_HASHTABLE(OBJ_PROP(o));
100 zend_hash_init(OBJ_PROP(o), 0, NULL, ZVAL_PTR_DTOR, 0);
101 zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
102
103 ov.handle = zend_objects_store_put(o, (zend_objects_store_dtor_t) zend_objects_destroy_object, http_requestpool_object_free, NULL TSRMLS_CC);
104 ov.handlers = &http_requestpool_object_handlers;
105
106 return ov;
107 }
108
109 static inline void _http_requestpool_object_declare_default_properties(TSRMLS_D)
110 {
111 zend_class_entry *ce = http_requestpool_object_ce;
112
113 DCL_PROP_N(PROTECTED, pool);
114 }
115
116 void _http_requestpool_object_free(zend_object *object TSRMLS_DC)
117 {
118 http_requestpool_object *o = (http_requestpool_object *) object;
119
120 if (OBJ_PROP(o)) {
121 zend_hash_destroy(OBJ_PROP(o));
122 FREE_HASHTABLE(OBJ_PROP(o));
123 }
124 http_request_pool_dtor(&o->pool);
125 efree(o);
126 }
127
128 /* ### USERLAND ### */
129
130 /* {{{ proto void HttpRequestPool::__construct([HttpRequest request[, ...]])
131 *
132 * Instantiate a new HttpRequestPool object. An HttpRequestPool is
133 * able to send several HttpRequests in parallel.
134 *
135 * Example:
136 * <pre>
137 * <?php
138 * $urls = array('www.php.net', 'pecl.php.net', 'pear.php.net')
139 * $pool = new HttpRequestPool;
140 * foreach ($urls as $url) {
141 * $req[$url] = new HttpRequest("http://$url", HTTP_HEAD);
142 * $pool->attach($req[$url]);
143 * }
144 * $pool->send();
145 * foreach ($urls as $url) {
146 * printf("%s (%s) is %s\n",
147 * $url, $req[$url]->getResponseInfo('effective_url'),
148 * $r->getResponseCode() == 200 ? 'alive' : 'not alive'
149 * );
150 * }
151 * ?>
152 * </pre>
153 */
154 PHP_METHOD(HttpRequestPool, __construct)
155 {
156 int argc = ZEND_NUM_ARGS();
157 zval ***argv = safe_emalloc(argc, sizeof(zval *), 0);
158 getObject(http_requestpool_object, obj);
159
160 if (SUCCESS == zend_get_parameters_array_ex(argc, argv)) {
161 int i;
162
163 for (i = 0; i < argc; ++i) {
164 if (Z_TYPE_PP(argv[i]) == IS_OBJECT && instanceof_function(Z_OBJCE_PP(argv[i]), http_request_object_ce TSRMLS_CC)) {
165 http_request_pool_attach(&obj->pool, *(argv[i]));
166 }
167 }
168 }
169 efree(argv);
170 }
171 /* }}} */
172
173 /* {{{ proto void HttpRequestPool::__destruct()
174 *
175 * Clean up HttpRequestPool object.
176 */
177 PHP_METHOD(HttpRequestPool, __destruct)
178 {
179 getObject(http_requestpool_object, obj);
180
181 NO_ARGS;
182
183 http_request_pool_detach_all(&obj->pool);
184 }
185 /* }}} */
186
187 /* {{{ proto void HttpRequestPool::reset()
188 *
189 * Detach all attached HttpRequest objects.
190 */
191 PHP_METHOD(HttpRequestPool, reset)
192 {
193 getObject(http_requestpool_object, obj);
194
195 NO_ARGS;
196
197 http_request_pool_detach_all(&obj->pool);
198 }
199
200 /* {{{ proto bool HttpRequestPool::attach(HttpRequest request)
201 *
202 * Attach an HttpRequest object to this HttpRequestPool.
203 * NOTE: set all options prior attaching!
204 */
205 PHP_METHOD(HttpRequestPool, attach)
206 {
207 zval *request;
208 STATUS status = FAILURE;
209 getObject(http_requestpool_object, obj);
210
211 SET_EH_THROW_HTTP();
212 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
213 status = http_request_pool_attach(&obj->pool, request);
214 }
215 SET_EH_NORMAL();
216 RETURN_SUCCESS(status);
217 }
218 /* }}} */
219
220 /* {{{ proto bool HttpRequestPool::detach(HttpRequest request)
221 *
222 * Detach an HttpRequest object from this HttpRequestPool.
223 */
224 PHP_METHOD(HttpRequestPool, detach)
225 {
226 zval *request;
227 STATUS status = FAILURE;
228 getObject(http_requestpool_object, obj);
229
230 SET_EH_THROW_HTTP();
231 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
232 status = http_request_pool_detach(&obj->pool, request);
233 }
234 SET_EH_NORMAL();
235 RETURN_SUCCESS(status);
236 }
237 /* }}} */
238
239 /* {{{ proto bool HttpRequestPool::send()
240 *
241 * Send all attached HttpRequest objects in parallel.
242 */
243 PHP_METHOD(HttpRequestPool, send)
244 {
245 STATUS status;
246 getObject(http_requestpool_object, obj);
247
248 NO_ARGS;
249
250 SET_EH_THROW_HTTP();
251 status = http_request_pool_send(&obj->pool);
252 SET_EH_NORMAL();
253
254 RETURN_SUCCESS(status);
255 }
256 /* }}} */
257
258 /* {{{ proto protected bool HttpRequestPool::socketSend()
259 *
260 * Usage:
261 * <pre>
262 * <?php
263 * while ($pool->socketSend()) {
264 * do_something_else();
265 * if (!$pool->socketSelect()) {
266 * die('Socket error');
267 * }
268 * }
269 * $pool->socketRead();
270 * ?>
271 * </pre>
272 */
273 PHP_METHOD(HttpRequestPool, socketSend)
274 {
275 getObject(http_requestpool_object, obj);
276
277 NO_ARGS;
278
279 RETURN_BOOL(0 < http_request_pool_perform(&obj->pool));
280 }
281 /* }}} */
282
283 /* {{{ proto protected bool HttpRequestPool::socketSelect()
284 *
285 * See HttpRequestPool::socketSend().
286 */
287 PHP_METHOD(HttpRequestPool, socketSelect)
288 {
289 getObject(http_requestpool_object, obj);
290
291 NO_ARGS;
292
293 RETURN_SUCCESS(http_request_pool_select(&obj->pool));
294 }
295 /* }}} */
296
297 /* {{{ proto protected void HttpRequestPool::socketRead()
298 *
299 * See HttpRequestPool::socketSend().
300 */
301 PHP_METHOD(HttpRequestPool, socketRead)
302 {
303 getObject(http_requestpool_object, obj);
304
305 NO_ARGS;
306
307 zend_llist_apply(&obj->pool.handles, (llist_apply_func_t) http_request_pool_responsehandler TSRMLS_CC);
308 }
309 /* }}} */
310
311 #endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
312
313 /*
314 * Local variables:
315 * tab-width: 4
316 * c-basic-offset: 4
317 * End:
318 * vim600: noet sw=4 ts=4 fdm=marker
319 * vim<600: noet sw=4 ts=4
320 */
321