#include "php_http_api.h"
#include "php_http_client.h"
#include "php_http_client_curl_event.h"
+#include "php_http_client_curl_user.h"
#if PHP_HTTP_HAVE_CURL
#endif
{
php_http_client_curl_handler_t *h = ctx;
- zend_bool update = 0;
if (h->progress.dl.total != dltotal
|| h->progress.dl.now != dlnow
|| h->progress.ul.total != ultotal
|| h->progress.ul.now != ulnow
) {
- update = 1;
-
h->progress.dl.total = dltotal;
h->progress.dl.now = dlnow;
h->progress.ul.total = ultotal;
h->progress.ul.now = ulnow;
}
- if (update && h->client->callback.progress.func) {
+ if (h->client->callback.progress.func) {
h->client->callback.progress.func(h->client->callback.progress.arg, h->client, &h->queue, &h->progress);
}
static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data, size_t length, void *ctx)
{
php_http_client_curl_handler_t *h = ctx;
+ unsigned utype = PHP_HTTP_CLIENT_DEBUG_INFO;
/* catch progress */
switch (type) {
h->client->callback.progress.func(h->client->callback.progress.arg, h->client, &h->queue, &h->progress);
}
break;
+
case CURLINFO_HEADER_OUT:
- case CURLINFO_DATA_OUT:
+ utype |= PHP_HTTP_CLIENT_DEBUG_HEADER;
+ goto data_out;
+
case CURLINFO_SSL_DATA_OUT:
+ utype |= PHP_HTTP_CLIENT_DEBUG_SSL;
+ goto data_out;
+
+ case CURLINFO_DATA_OUT:
+ data_out:
+ utype |= PHP_HTTP_CLIENT_DEBUG_OUT;
h->progress.info = "send";
break;
+
case CURLINFO_HEADER_IN:
- case CURLINFO_DATA_IN:
+ utype |= PHP_HTTP_CLIENT_DEBUG_HEADER;
+ goto data_in;
+
case CURLINFO_SSL_DATA_IN:
+ utype |= PHP_HTTP_CLIENT_DEBUG_SSL;
+ goto data_in;
+
+ case CURLINFO_DATA_IN:
+ data_in:
+ utype |= PHP_HTTP_CLIENT_DEBUG_IN;
h->progress.info = "receive";
break;
+
default:
break;
}
+ if (h->client->callback.debug.func) {
+ h->client->callback.debug.func(h->client->callback.debug.arg, h->client, &h->queue, utype, data, length);
+ }
+
#if 0
/* debug */
_dpf(type, data, length);
}
}
+void php_http_client_curl_loop(php_http_client_t *client, curl_socket_t s, int curl_action)
+{
+ CURLMcode rc;
+ php_http_client_curl_t *curl = client->ctx;
+ TSRMLS_FETCH_FROM_CTX(client->ts);
+
+#if DBG_EVENTS
+ fprintf(stderr, "H");
+#endif
+
+ do {
+ rc = curl_multi_socket_action(curl->handle->multi, s, curl_action, &curl->unfinished);
+ } while (CURLM_CALL_MULTI_PERFORM == rc);
+
+ if (CURLM_OK != rc) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", curl_multi_strerror(rc));
+ }
+
+ php_http_client_curl_responsehandler(client);
+}
+
/* curl options */
static php_http_options_t php_http_curle_options, php_http_curlm_options;
}
#endif
-#if PHP_HTTP_HAVE_EVENT
-static inline ZEND_RESULT_CODE php_http_curlm_use_eventloop(php_http_client_t *h, zend_bool enable)
+static inline ZEND_RESULT_CODE php_http_curlm_use_eventloop(php_http_client_t *h, php_http_client_curl_ops_t *ev_ops, zval *init_data)
{
php_http_client_curl_t *curl = h->ctx;
+ void *ev_ctx;
- if (enable) {
- if (!curl->ev_ops) {
- if (!(curl->ev_ops = php_http_client_curl_event_ops_get())) {
- return FAILURE;
- }
- }
- if (curl->ev_ops && !curl->ev_ctx) {
- if (!(curl->ev_ctx = curl->ev_ops->init(h))) {
- return FAILURE;
- }
+ if (ev_ops) {
+ if (!(ev_ctx = ev_ops->init(h, init_data))) {
+ return FAILURE;
}
+ curl->ev_ctx = ev_ctx;
+ curl->ev_ops = ev_ops;
} else {
if (curl->ev_ops) {
if (curl->ev_ctx) {
static ZEND_RESULT_CODE php_http_curlm_option_set_use_eventloop(php_http_option_t *opt, zval *value, void *userdata)
{
php_http_client_t *client = userdata;
+ php_http_client_curl_ops_t *ev_ops = NULL;
+ TSRMLS_FETCH_FROM_CTX(client->ts);
- if (Z_TYPE_P(value) == IS_OBJECT /* && instanceof_function */) {
- abort();
+ if (Z_TYPE_P(value) == IS_OBJECT && instanceof_function(Z_OBJCE_P(value), php_http_client_curl_user_class_entry TSRMLS_CC)) {
+ ev_ops = php_http_client_curl_user_ops_get();
+#if PHP_HTTP_HAVE_EVENT
+ } else if (value && z_is_true(value)) {
+ ev_ops = php_http_client_curl_event_ops_get();
+#endif
}
- return php_http_curlm_use_eventloop(client, value && z_is_true(value));
+
+ return php_http_curlm_use_eventloop(client, ev_ops, value);
}
-#endif
static ZEND_RESULT_CODE php_http_curlm_option_set_share_cookies(php_http_option_t *opt, zval *value, void *userdata)
{
}
#endif
/* events */
-#if PHP_HTTP_HAVE_EVENT
- if ((opt = php_http_option_register(registry, ZEND_STRL("use_eventloop"), 0, IS_BOOL))) {
+ if ((opt = php_http_option_register(registry, ZEND_STRL("use_eventloop"), 0, 0))) {
opt->setter = php_http_curlm_option_set_use_eventloop;
}
-#endif
/* share */
if ((opt = php_http_option_register(registry, ZEND_STRL("share_cookies"), 0, IS_BOOL))) {
opt->setter = php_http_curlm_option_set_share_cookies;
if (curl->ev_ops) {
curl->ev_ops->dtor(&curl->ev_ctx);
+ curl->ev_ops = NULL;
}
curl->unfinished = 0;
php_http_client_curl_handler_t *handler = enqueue->opaque;
TSRMLS_FETCH_FROM_CTX(h->ts);
+ if (h->callback.depth) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not dequeue request while executing callbacks");
+ return FAILURE;
+ }
+
php_http_client_curl_handler_clear(handler);
if (CURLM_OK == (rs = curl_multi_remove_handle(curl->handle->multi, handler->handle))) {
zend_llist_del_element(&h->requests, handler->handle, (int (*)(void *, void *)) compare_queue);
{
php_http_client_curl_t *curl = h->ctx;
- if (curl->ev_ops) {
- curl->ev_ops->once(curl->ev_ctx);
- } else {
- while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl->handle->multi, &curl->unfinished));
- }
+ if (!h->callback.depth) {
+ if (curl->ev_ops) {
+ curl->ev_ops->once(curl->ev_ctx);
+ } else {
+ while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl->handle->multi, &curl->unfinished));
+ }
- php_http_client_curl_responsehandler(h);
+ php_http_client_curl_responsehandler(h);
+ }
return curl->unfinished;
-
}
static ZEND_RESULT_CODE php_http_client_curl_exec(php_http_client_t *h)
php_http_client_curl_t *curl = h->ctx;
TSRMLS_FETCH_FROM_CTX(h->ts);
- if (curl->ev_ops) {
- return curl->ev_ops->exec(curl->ev_ctx);
- }
+ if (!h->callback.depth) {
+ if (curl->ev_ops) {
+ return curl->ev_ops->exec(curl->ev_ctx);
+ }
- while (php_http_client_curl_once(h) && !EG(exception)) {
- if (SUCCESS != php_http_client_curl_wait(h, NULL)) {
+ while (php_http_client_curl_once(h) && !EG(exception)) {
+ if (SUCCESS != php_http_client_curl_wait(h, NULL)) {
#ifdef PHP_WIN32
- /* see http://msdn.microsoft.com/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "WinSock error: %d", WSAGetLastError());
+ /* see http://msdn.microsoft.com/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "WinSock error: %d", WSAGetLastError());
#else
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
#endif
- return FAILURE;
+ return FAILURE;
+ }
}
}
case PHP_HTTP_CLIENT_OPT_USE_EVENTS:
#if PHP_HTTP_HAVE_EVENT
- return php_http_curlm_use_eventloop(h, *(zend_bool *) arg);
+ return php_http_curlm_use_eventloop(h, (*(zend_bool *) arg)
+ ? php_http_client_curl_event_ops_get()
+ : NULL, NULL);
break;
#endif