2 +--------------------------------------------------------------------+
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2004-2006, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
15 #define HTTP_WANT_CURL
18 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
20 #include "php_http_api.h"
21 #include "php_http_request_datashare_api.h"
22 #include "php_http_request_api.h"
23 #include "php_http_request_object.h"
24 #ifdef HTTP_HAVE_PERSISTENT_HANDLES
25 # include "php_http_persistent_handle_api.h"
28 #ifdef HTTP_HAVE_PERSISTENT_HANDLES
29 # define HTTP_CURL_SHARE_CTOR(ch) (SUCCESS == http_persistent_handle_acquire("http_request_datashare", &(ch)))
30 # define HTTP_CURL_SHARE_DTOR(chp) http_persistent_handle_release("http_request_datashare", (chp))
31 # define HTTP_CURL_SLOCK_CTOR(l) (SUCCESS == http_persistent_handle_acquire("http_request_datashare_lock", (void *) &(l)))
32 # define HTTP_CURL_SLOCK_DTOR(lp) http_persistent_handle_release("http_request_datashare_lock", (void *) (lp))
34 # define HTTP_CURL_SHARE_CTOR(ch) ((ch) = curl_share_init())
35 # define HTTP_CURL_SHARE_DTOR(chp) curl_share_cleanup(*(chp)); *(chp) = NULL
36 # define HTTP_CURL_SLOCK_CTOR(l) ((l) = http_request_datashare_locks_init())
37 # define HTTP_CURL_SLOCK_DTOR(lp) http_request_datashare_locks_dtor(*(lp)); *(lp) = NULL
40 static HashTable http_request_datashare_options
;
41 static http_request_datashare http_request_datashare_global
;
42 static int http_request_datashare_compare_handles(void *h1
, void *h2
);
43 static void http_request_datashare_destroy_handles(void *el
);
45 static void *http_request_datashare_locks_init(void);
46 static void http_request_datashare_locks_dtor(void *l
);
47 static void http_request_datashare_lock_func(CURL
*handle
, curl_lock_data data
, curl_lock_access locktype
, void *userptr
);
48 static void http_request_datashare_unlock_func(CURL
*handle
, curl_lock_data data
, void *userptr
);
51 http_request_datashare
*_http_request_datashare_global_get(void)
53 return &http_request_datashare_global
;
56 PHP_MINIT_FUNCTION(http_request_datashare
)
60 #ifdef HTTP_HAVE_PERSISTENT_HANDLES
61 if (SUCCESS
!= http_persistent_handle_provide("http_request_datashare", curl_share_init
, (http_persistent_handle_dtor
) curl_share_cleanup
)) {
65 if (SUCCESS
!= http_persistent_handle_provide("http_request_datashare_lock", http_request_datashare_locks_init
, http_request_datashare_locks_dtor
)) {
71 if (!http_request_datashare_init_ex(&http_request_datashare_global
, 1)) {
75 zend_hash_init(&http_request_datashare_options
, 4, NULL
, NULL
, 1);
76 #define ADD_DATASHARE_OPT(name, opt) \
78 zend_hash_add(&http_request_datashare_options, name, sizeof(name), &val, sizeof(curl_lock_data), NULL)
79 ADD_DATASHARE_OPT("cookie", CURL_LOCK_DATA_COOKIE
);
80 ADD_DATASHARE_OPT("dns", CURL_LOCK_DATA_DNS
);
81 ADD_DATASHARE_OPT("ssl", CURL_LOCK_DATA_SSL_SESSION
);
82 ADD_DATASHARE_OPT("connect", CURL_LOCK_DATA_CONNECT
);
87 PHP_MSHUTDOWN_FUNCTION(http_request_datashare
)
89 http_request_datashare_dtor(&http_request_datashare_global
);
90 zend_hash_destroy(&http_request_datashare_options
);
95 PHP_RINIT_FUNCTION(http_request_datashare
)
97 zend_llist_init(&HTTP_G
->request
.datashare
.handles
, sizeof(zval
*), http_request_datashare_destroy_handles
, 0);
102 PHP_RSHUTDOWN_FUNCTION(http_request_datashare
)
104 zend_llist_destroy(&HTTP_G
->request
.datashare
.handles
);
109 PHP_HTTP_API http_request_datashare
*_http_request_datashare_init_ex(http_request_datashare
*share
, zend_bool persistent TSRMLS_DC
)
111 zend_bool free_share
;
113 if ((free_share
= !share
)) {
114 share
= pemalloc(sizeof(http_request_datashare
), persistent
);
116 memset(share
, 0, sizeof(http_request_datashare
));
118 if (!HTTP_CURL_SHARE_CTOR(share
->ch
)) {
120 pefree(share
, persistent
);
125 if (!(share
->persistent
= persistent
)) {
126 share
->handle
.list
= emalloc(sizeof(zend_llist
));
127 zend_llist_init(share
->handle
.list
, sizeof(zval
*), ZVAL_PTR_DTOR
, 0);
130 if (HTTP_CURL_SLOCK_CTOR(share
->handle
.locks
)) {
131 curl_share_setopt(share
->ch
, CURLSHOPT_LOCKFUNC
, http_request_datashare_lock_func
);
132 curl_share_setopt(share
->ch
, CURLSHOPT_UNLOCKFUNC
, http_request_datashare_unlock_func
);
133 curl_share_setopt(share
->ch
, CURLSHOPT_USERDATA
, share
);
141 PHP_HTTP_API STATUS
_http_request_datashare_attach(http_request_datashare
*share
, zval
*request TSRMLS_DC
)
144 getObjectEx(http_request_object
, obj
, request
);
147 if (obj
->share
== share
) {
149 } else if (SUCCESS
!= http_request_datashare_detach(obj
->share
, request
)) {
154 HTTP_CHECK_CURL_INIT(obj
->request
->ch
, http_curl_init_ex(obj
->request
->ch
, obj
->request
), return FAILURE
);
155 if (CURLE_OK
!= (rc
= curl_easy_setopt(obj
->request
->ch
, CURLOPT_SHARE
, share
->ch
))) {
156 http_error_ex(HE_WARNING
, HTTP_E_REQUEST
, "Could not attach HttpRequest object(#%d) to the HttpRequestDataShare: %s", Z_OBJ_HANDLE_P(request
), curl_easy_strerror(rc
));
161 ZVAL_ADDREF(request
);
162 zend_llist_add_element(HTTP_RSHARE_HANDLES(share
), (void *) &request
);
167 PHP_HTTP_API STATUS
_http_request_datashare_detach(http_request_datashare
*share
, zval
*request TSRMLS_DC
)
170 getObjectEx(http_request_object
, obj
, request
);
173 http_error_ex(HE_WARNING
, HTTP_E_REQUEST
, "HttpRequest object(#%d) is not attached to any HttpRequestDataShare", Z_OBJ_HANDLE_P(request
));
174 } else if (obj
->share
!= share
) {
175 http_error_ex(HE_WARNING
, HTTP_E_REQUEST
, "HttpRequest object(#%d) is not attached to this HttpRequestDataShare", Z_OBJ_HANDLE_P(request
));
176 } else if (CURLE_OK
!= (rc
= curl_easy_setopt(obj
->request
->ch
, CURLOPT_SHARE
, NULL
))) {
177 http_error_ex(HE_WARNING
, HTTP_E_REQUEST
, "Could not detach HttpRequest object(#%d) from the HttpRequestDataShare: %s", Z_OBJ_HANDLE_P(request
), curl_share_strerror(rc
));
180 zend_llist_del_element(HTTP_RSHARE_HANDLES(share
), request
, http_request_datashare_compare_handles
);
186 PHP_HTTP_API
void _http_request_datashare_detach_all(http_request_datashare
*share TSRMLS_DC
)
190 while ((r
= zend_llist_get_first(HTTP_RSHARE_HANDLES(share
)))) {
191 http_request_datashare_detach(share
, *r
);
195 PHP_HTTP_API
void _http_request_datashare_dtor(http_request_datashare
*share TSRMLS_DC
)
197 if (!share
->persistent
) {
198 zend_llist_destroy(share
->handle
.list
);
199 efree(share
->handle
.list
);
201 HTTP_CURL_SHARE_DTOR(&share
->ch
);
203 if (share
->persistent
) {
204 HTTP_CURL_SLOCK_DTOR(&share
->handle
.locks
);
209 PHP_HTTP_API
void _http_request_datashare_free(http_request_datashare
**share TSRMLS_DC
)
211 http_request_datashare_dtor(*share
);
212 pefree(*share
, (*share
)->persistent
);
216 PHP_HTTP_API STATUS
_http_request_datashare_set(http_request_datashare
*share
, const char *option
, size_t option_len
, zend_bool enable TSRMLS_DC
)
221 if (SUCCESS
== zend_hash_find(&http_request_datashare_options
, (char *) option
, option_len
+ 1, (void *) &opt
)) {
222 if (CURLSHE_OK
== (rc
= curl_share_setopt(share
->ch
, enable
? CURLSHOPT_SHARE
: CURLSHOPT_UNSHARE
, *opt
))) {
225 http_error_ex(HE_WARNING
, HTTP_E_REQUEST
, "Could not %s sharing of %s data: %s", enable
? "enable" : "disable", option
, curl_share_strerror(rc
));
230 static int http_request_datashare_compare_handles(void *h1
, void *h2
)
232 return (Z_OBJ_HANDLE_PP((zval
**) h1
) == Z_OBJ_HANDLE_P((zval
*) h2
));
235 static void http_request_datashare_destroy_handles(void *el
)
237 zval
**r
= (zval
**) el
;
240 { /* gcc 2.95 needs these braces */
241 getObjectEx(http_request_object
, obj
, *r
);
243 curl_easy_setopt(obj
->request
->ch
, CURLOPT_SHARE
, NULL
);
249 static void *http_request_datashare_locks_init(void)
252 http_request_datashare_lock
*locks
= pecalloc(CURL_LOCK_DATA_LAST
, sizeof(http_request_datashare_lock
), 1);
255 for (i
= 0; i
< CURL_LOCK_DATA_LAST
; ++i
) {
256 locks
[i
].mx
= tsrm_mutex_alloc();
263 static void http_request_datashare_locks_dtor(void *l
)
266 http_request_datashare_lock
*locks
= (http_request_datashare_lock
*) l
;
268 for (i
= 0; i
< CURL_LOCK_DATA_LAST
; ++i
) {
269 tsrm_mutex_free(locks
[i
].mx
);
274 static void http_request_datashare_lock_func(CURL
*handle
, curl_lock_data data
, curl_lock_access locktype
, void *userptr
)
276 http_request_datashare
*share
= (http_request_datashare
*) userptr
;
278 /* TSRM can't distinguish shared/exclusive locks */
279 tsrm_mutex_lock(share
->handle
.locks
[data
].mx
);
280 share
->handle
.locks
[data
].ch
= handle
;
283 static void http_request_datashare_unlock_func(CURL
*handle
, curl_lock_data data
, void *userptr
)
285 http_request_datashare
*share
= (http_request_datashare
*) userptr
;
287 if (share
->handle
.locks
[data
].ch
== handle
) {
288 tsrm_mutex_unlock(share
->handle
.locks
[data
].mx
);
293 #endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
301 * vim600: noet sw=4 ts=4 fdm=marker
302 * vim<600: noet sw=4 ts=4