LTP GCOV extension - code coverage report
Current view: directory - ext/http - http_request_datashare_api.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 91
Code covered: 81.3 % Executed lines: 74
Legend: not executed executed

       1                 : /*
       2                 :     +--------------------------------------------------------------------+
       3                 :     | PECL :: http                                                       |
       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-2007, Michael Wallner <mike@php.net>            |
      10                 :     +--------------------------------------------------------------------+
      11                 : */
      12                 : 
      13                 : /* $Id: http_request_datashare_api.c,v 1.10 2007/02/09 14:19:39 mike Exp $ */
      14                 : 
      15                 : #define HTTP_WANT_CURL
      16                 : #include "php_http.h"
      17                 : 
      18                 : #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
      19                 : 
      20                 : #include "php_http_api.h"
      21                 : #include "php_http_persistent_handle_api.h"
      22                 : #include "php_http_request_datashare_api.h"
      23                 : #include "php_http_request_api.h"
      24                 : #include "php_http_request_object.h"
      25                 : 
      26                 : static HashTable http_request_datashare_options;
      27                 : static http_request_datashare http_request_datashare_global;
      28                 : static int http_request_datashare_compare_handles(void *h1, void *h2);
      29                 : static void http_request_datashare_destroy_handles(void *el);
      30                 : #ifdef ZTS
      31                 : static void *http_request_datashare_locks_init(void);
      32                 : static void http_request_datashare_locks_dtor(void *l);
      33                 : static void http_request_datashare_lock_func(CURL *handle, curl_lock_data data, curl_lock_access locktype, void *userptr);
      34                 : static void http_request_datashare_unlock_func(CURL *handle, curl_lock_data data, void *userptr);
      35                 : #endif
      36                 : 
      37                 : http_request_datashare *_http_request_datashare_global_get(void)
      38               1 : {
      39               1 :         return &http_request_datashare_global;
      40                 : }
      41                 : 
      42                 : PHP_MINIT_FUNCTION(http_request_datashare)
      43             220 : {
      44                 :         curl_lock_data val;
      45                 :         
      46             220 :         if (SUCCESS != http_persistent_handle_provide("http_request_datashare", curl_share_init, (http_persistent_handle_dtor) curl_share_cleanup, NULL)) {
      47               0 :                 return FAILURE;
      48                 :         }
      49                 : #ifdef ZTS
      50                 :         if (SUCCESS != http_persistent_handle_provide("http_request_datashare_lock", http_request_datashare_locks_init, http_request_datashare_locks_dtor, NULL)) {
      51                 :                 return FAILURE;
      52                 :         }
      53                 : #endif
      54                 :         
      55             220 :         if (!http_request_datashare_init_ex(&http_request_datashare_global, 1)) {
      56               0 :                 return FAILURE;
      57                 :         }
      58                 :         
      59             220 :         zend_hash_init(&http_request_datashare_options, 4, NULL, NULL, 1);
      60                 : #define ADD_DATASHARE_OPT(name, opt) \
      61                 :         val = opt; \
      62                 :         zend_hash_add(&http_request_datashare_options, name, sizeof(name), &val, sizeof(curl_lock_data), NULL)
      63             220 :         ADD_DATASHARE_OPT("cookie", CURL_LOCK_DATA_COOKIE);
      64             220 :         ADD_DATASHARE_OPT("dns", CURL_LOCK_DATA_DNS);
      65             220 :         ADD_DATASHARE_OPT("ssl", CURL_LOCK_DATA_SSL_SESSION);
      66             220 :         ADD_DATASHARE_OPT("connect", CURL_LOCK_DATA_CONNECT);
      67                 :         
      68             220 :         return SUCCESS;
      69                 : }
      70                 : 
      71                 : PHP_MSHUTDOWN_FUNCTION(http_request_datashare)
      72             219 : {
      73             219 :         http_request_datashare_dtor(&http_request_datashare_global);
      74             219 :         zend_hash_destroy(&http_request_datashare_options);
      75                 :         
      76             219 :         return SUCCESS;
      77                 : }
      78                 : 
      79                 : PHP_RINIT_FUNCTION(http_request_datashare)
      80             219 : {
      81             219 :         zend_llist_init(&HTTP_G->request.datashare.handles, sizeof(zval *), http_request_datashare_destroy_handles, 0);
      82                 :         
      83             219 :         return SUCCESS;
      84                 : }
      85                 : 
      86                 : PHP_RSHUTDOWN_FUNCTION(http_request_datashare)
      87             219 : {
      88             219 :         zend_llist_destroy(&HTTP_G->request.datashare.handles);
      89                 :         
      90             219 :         return SUCCESS;
      91                 : }
      92                 : 
      93                 : PHP_HTTP_API http_request_datashare *_http_request_datashare_init_ex(http_request_datashare *share, zend_bool persistent TSRMLS_DC)
      94             221 : {
      95                 :         zend_bool free_share;
      96                 :         
      97             221 :         if ((free_share = !share)) {
      98               1 :                 share = pemalloc(sizeof(http_request_datashare), persistent);
      99                 :         }
     100             221 :         memset(share, 0, sizeof(http_request_datashare));
     101                 :         
     102             221 :         if (SUCCESS != http_persistent_handle_acquire("http_request_datashare", &share->ch)) {
     103               0 :                 if (free_share) {
     104               0 :                         pefree(share, persistent);
     105                 :                 }
     106               0 :                 return NULL;
     107                 :         }
     108                 :         
     109             221 :         if (!(share->persistent = persistent)) {
     110               1 :                 share->handle.list = emalloc(sizeof(zend_llist));
     111               1 :                 zend_llist_init(share->handle.list, sizeof(zval *), ZVAL_PTR_DTOR, 0);
     112                 : #ifdef ZTS
     113                 :         } else {
     114                 :                 if (SUCCESS == http_persistent_handle_acquire("http_request_datashare_lock", (void *) &share->handle.locks)) {
     115                 :                         curl_share_setopt(share->ch, CURLSHOPT_LOCKFUNC, http_request_datashare_lock_func);
     116                 :                         curl_share_setopt(share->ch, CURLSHOPT_UNLOCKFUNC, http_request_datashare_unlock_func);
     117                 :                         curl_share_setopt(share->ch, CURLSHOPT_USERDATA, share->handle.locks);
     118                 :                 }
     119                 : #endif
     120                 :         }
     121                 :         
     122             221 :         return share;
     123                 : }
     124                 : 
     125                 : PHP_HTTP_API STATUS _http_request_datashare_attach(http_request_datashare *share, zval *request TSRMLS_DC)
     126               4 : {
     127                 :         CURLcode rc;
     128               4 :         getObjectEx(http_request_object, obj, request);
     129                 :         
     130               4 :         if (obj->share) {
     131               0 :                 if (obj->share == share)  {
     132               0 :                         return SUCCESS;
     133               0 :                 } else if (SUCCESS != http_request_datashare_detach(obj->share, request)) {
     134               0 :                         return FAILURE;
     135                 :                 }
     136                 :         }
     137                 :         
     138               4 :         HTTP_CHECK_CURL_INIT(obj->request->ch, http_curl_init_ex(obj->request->ch, obj->request), return FAILURE);
     139               4 :         if (CURLE_OK != (rc = curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, share->ch))) {
     140               0 :                 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));
     141               0 :                 return FAILURE;
     142                 :         }
     143                 :         
     144               4 :         obj->share = share;
     145               4 :         ZVAL_ADDREF(request);
     146               4 :         zend_llist_add_element(HTTP_RSHARE_HANDLES(share), (void *) &request);
     147                 :         
     148               4 :         return SUCCESS;
     149                 : }
     150                 : 
     151                 : PHP_HTTP_API STATUS _http_request_datashare_detach(http_request_datashare *share, zval *request TSRMLS_DC)
     152               4 : {
     153                 :         CURLcode rc;
     154               4 :         getObjectEx(http_request_object, obj, request);
     155                 :         
     156               4 :         if (!obj->share) {
     157               0 :                 http_error_ex(HE_WARNING, HTTP_E_REQUEST, "HttpRequest object(#%d) is not attached to any HttpRequestDataShare", Z_OBJ_HANDLE_P(request));
     158               4 :         } else if (obj->share != share) {
     159               0 :                 http_error_ex(HE_WARNING, HTTP_E_REQUEST, "HttpRequest object(#%d) is not attached to this HttpRequestDataShare", Z_OBJ_HANDLE_P(request));
     160               4 :         } else if (CURLE_OK != (rc = curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, NULL))) {
     161               0 :                 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));
     162                 :         } else {
     163               4 :                 obj->share = NULL;
     164               4 :                 zend_llist_del_element(HTTP_RSHARE_HANDLES(share), request, http_request_datashare_compare_handles);
     165               4 :                 return SUCCESS;
     166                 :         }
     167               0 :         return FAILURE;
     168                 : }
     169                 : 
     170                 : PHP_HTTP_API void _http_request_datashare_detach_all(http_request_datashare *share TSRMLS_DC)
     171               4 : {
     172                 :         zval **r;
     173                 :         
     174              12 :         while ((r = zend_llist_get_first(HTTP_RSHARE_HANDLES(share)))) {
     175               4 :                 http_request_datashare_detach(share, *r);
     176                 :         }
     177               4 : }
     178                 : 
     179                 : PHP_HTTP_API void _http_request_datashare_dtor(http_request_datashare *share TSRMLS_DC)
     180             220 : {
     181             220 :         if (!share->persistent) {
     182               1 :                 zend_llist_destroy(share->handle.list);
     183               1 :                 efree(share->handle.list);
     184                 :         }
     185             220 :         http_persistent_handle_release("http_request_datashare", &share->ch);
     186                 : #ifdef ZTS
     187                 :         if (share->persistent) {
     188                 :                 http_persistent_handle_release("http_request_datashare_lock", (void *) &share->handle.locks);
     189                 :         }
     190                 : #endif
     191             220 : }
     192                 : 
     193                 : PHP_HTTP_API void _http_request_datashare_free(http_request_datashare **share TSRMLS_DC)
     194               1 : {
     195               1 :         http_request_datashare_dtor(*share);
     196               1 :         pefree(*share, (*share)->persistent);
     197               1 :         *share = NULL;
     198               1 : }
     199                 : 
     200                 : PHP_HTTP_API STATUS _http_request_datashare_set(http_request_datashare *share, const char *option, size_t option_len, zend_bool enable TSRMLS_DC)
     201               4 : {
     202                 :         curl_lock_data *opt;
     203                 :         CURLSHcode rc;
     204                 :         
     205               4 :         if (SUCCESS == zend_hash_find(&http_request_datashare_options, (char *) option, option_len + 1, (void *) &opt)) {
     206               4 :                 if (CURLSHE_OK == (rc = curl_share_setopt(share->ch, enable ? CURLSHOPT_SHARE : CURLSHOPT_UNSHARE, *opt))) {
     207               4 :                         return SUCCESS;
     208                 :                 }
     209               0 :                 http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not %s sharing of %s data: %s",  enable ? "enable" : "disable", option, curl_share_strerror(rc));
     210                 :         }
     211               0 :         return FAILURE;
     212                 : }
     213                 : 
     214                 : static int http_request_datashare_compare_handles(void *h1, void *h2)
     215               4 : {
     216               4 :         return (Z_OBJ_HANDLE_PP((zval **) h1) == Z_OBJ_HANDLE_P((zval *) h2));
     217                 : }
     218                 : 
     219                 : static void http_request_datashare_destroy_handles(void *el)
     220               2 : {
     221               2 :         zval **r = (zval **) el;
     222                 :         TSRMLS_FETCH();
     223                 :         
     224                 :         { /* gcc 2.95 needs these braces */
     225               2 :                 getObjectEx(http_request_object, obj, *r);
     226                 :                 
     227               2 :                 curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, NULL);
     228               2 :                 zval_ptr_dtor(r);
     229                 :         }
     230               2 : }
     231                 : 
     232                 : #ifdef ZTS
     233                 : static void *http_request_datashare_locks_init(void)
     234                 : {
     235                 :         int i;
     236                 :         http_request_datashare_lock *locks = pecalloc(CURL_LOCK_DATA_LAST, sizeof(http_request_datashare_lock), 1);
     237                 :         
     238                 :         if (locks) {
     239                 :                 for (i = 0; i < CURL_LOCK_DATA_LAST; ++i) {
     240                 :                         locks[i].mx = tsrm_mutex_alloc();
     241                 :                 }
     242                 :         }
     243                 :         
     244                 :         return locks;
     245                 : }
     246                 : 
     247                 : static void http_request_datashare_locks_dtor(void *l)
     248                 : {
     249                 :         int i;
     250                 :         http_request_datashare_lock *locks = (http_request_datashare_lock *) l;
     251                 :         
     252                 :         for (i = 0; i < CURL_LOCK_DATA_LAST; ++i) {
     253                 :                 tsrm_mutex_free(locks[i].mx);
     254                 :         }
     255                 :         pefree(locks, 1);
     256                 : }
     257                 : 
     258                 : static void http_request_datashare_lock_func(CURL *handle, curl_lock_data data, curl_lock_access locktype, void *userptr)
     259                 : {
     260                 :         http_request_datashare_lock *locks = (http_request_datashare_lock *) userptr;
     261                 :         
     262                 :         /* TSRM can't distinguish shared/exclusive locks */
     263                 :         tsrm_mutex_lock(locks[data].mx);
     264                 :         locks[data].ch = handle;
     265                 : }
     266                 : 
     267                 : static void http_request_datashare_unlock_func(CURL *handle, curl_lock_data data, void *userptr)
     268                 : {
     269                 :         http_request_datashare_lock *locks = (http_request_datashare_lock *) userptr;
     270                 :         
     271                 :         if (locks[data].ch == handle) {
     272                 :                 tsrm_mutex_unlock(locks[data].mx);
     273                 :         }
     274                 : }
     275                 : #endif
     276                 : 
     277                 : #endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
     278                 : 
     279                 : 
     280                 : /*
     281                 :  * Local variables:
     282                 :  * tab-width: 4
     283                 :  * c-basic-offset: 4
     284                 :  * End:
     285                 :  * vim600: noet sw=4 ts=4 fdm=marker
     286                 :  * vim<600: noet sw=4 ts=4
     287                 :  */
     288                 : 

Generated by: LTP GCOV extension version 1.5