Annotation of embedaddon/php/ext/curl/multi.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    +----------------------------------------------------------------------+
        !             3:    | PHP Version 5                                                        |
        !             4:    +----------------------------------------------------------------------+
        !             5:    | Copyright (c) 1997-2012 The PHP Group                                |
        !             6:    +----------------------------------------------------------------------+
        !             7:    | This source file is subject to version 3.01 of the PHP license,      |
        !             8:    | that is bundled with this package in the file LICENSE, and is        |
        !             9:    | available through the world-wide-web at the following url:           |
        !            10:    | http://www.php.net/license/3_01.txt                                  |
        !            11:    | If you did not receive a copy of the PHP license and are unable to   |
        !            12:    | obtain it through the world-wide-web, please send a note to          |
        !            13:    | license@php.net so we can mail you a copy immediately.               |
        !            14:    +----------------------------------------------------------------------+
        !            15:    | Author: Sterling Hughes <sterling@php.net>                           |
        !            16:    +----------------------------------------------------------------------+
        !            17: */
        !            18: 
        !            19: /* $Id: multi.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            20: 
        !            21: #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
        !            22: 
        !            23: #ifdef HAVE_CONFIG_H
        !            24: #include "config.h"
        !            25: #endif
        !            26: 
        !            27: #include "php.h"
        !            28: 
        !            29: #if HAVE_CURL
        !            30: 
        !            31: #include "php_curl.h"
        !            32: 
        !            33: #include <curl/curl.h>
        !            34: #include <curl/multi.h>
        !            35: 
        !            36: #ifdef HAVE_SYS_SELECT_H
        !            37: #include <sys/select.h>
        !            38: #endif
        !            39: 
        !            40: #ifdef HAVE_SYS_TIME_H
        !            41: #include <sys/time.h>
        !            42: #endif
        !            43: 
        !            44: #ifdef HAVE_SYS_TYPES_H
        !            45: #include <sys/types.h>
        !            46: #endif
        !            47: 
        !            48: #ifdef HAVE_UNISTD_H
        !            49: #include <unistd.h>
        !            50: #endif
        !            51: 
        !            52: /* {{{ proto resource curl_multi_init(void)
        !            53:    Returns a new cURL multi handle */
        !            54: PHP_FUNCTION(curl_multi_init)
        !            55: {
        !            56:        php_curlm *mh;
        !            57:        
        !            58:        if (zend_parse_parameters_none() == FAILURE) {
        !            59:                return;
        !            60:        }
        !            61: 
        !            62:        mh = ecalloc(1, sizeof(php_curlm));
        !            63:        mh->multi = curl_multi_init();
        !            64: 
        !            65:        zend_llist_init(&mh->easyh, sizeof(zval), _php_curl_multi_cleanup_list, 0);
        !            66: 
        !            67:        ZEND_REGISTER_RESOURCE(return_value, mh, le_curl_multi_handle);
        !            68: }
        !            69: /* }}} */
        !            70: 
        !            71: /* {{{ proto int curl_multi_add_handle(resource mh, resource ch)
        !            72:    Add a normal cURL handle to a cURL multi handle */
        !            73: PHP_FUNCTION(curl_multi_add_handle)
        !            74: {
        !            75:        zval      *z_mh;
        !            76:        zval      *z_ch;
        !            77:        php_curlm *mh;
        !            78:        php_curl  *ch;
        !            79:        zval tmp_val;
        !            80: 
        !            81:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &z_mh, &z_ch) == FAILURE) {
        !            82:                return;
        !            83:        }
        !            84: 
        !            85:        ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
        !            86:        ZEND_FETCH_RESOURCE(ch, php_curl *, &z_ch, -1, le_curl_name, le_curl);
        !            87: 
        !            88:        _php_curl_cleanup_handle(ch);
        !            89:        ch->uses++;
        !            90: 
        !            91:        /* we want to create a copy of this zval that we store in the multihandle structure element "easyh" */
        !            92:        tmp_val = *z_ch;
        !            93:        zval_copy_ctor(&tmp_val);
        !            94: 
        !            95:        zend_llist_add_element(&mh->easyh, &tmp_val);
        !            96: 
        !            97:        RETURN_LONG((long) curl_multi_add_handle(mh->multi, ch->cp));   
        !            98: }
        !            99: /* }}} */
        !           100: 
        !           101: void _php_curl_multi_cleanup_list(void *data) /* {{{ */
        !           102: {
        !           103:        zval *z_ch = (zval *)data;
        !           104:        php_curl *ch;
        !           105:        TSRMLS_FETCH();
        !           106: 
        !           107:        if (!z_ch) {
        !           108:                return;
        !           109:        }
        !           110:        
        !           111:        ch = (php_curl *) zend_fetch_resource(&z_ch TSRMLS_CC, -1, le_curl_name, NULL, 1, le_curl);
        !           112:        if (!ch) {
        !           113:                return;
        !           114:        }
        !           115: 
        !           116:        if (ch->uses) { 
        !           117:                ch->uses--;
        !           118:        } else {
        !           119:                zend_list_delete(Z_LVAL_P(z_ch));
        !           120:        }
        !           121: }
        !           122: /* }}} */
        !           123: 
        !           124: /* Used internally as comparison routine passed to zend_list_del_element */
        !           125: static int curl_compare_resources( zval *z1, zval **z2 ) /* {{{ */
        !           126: {
        !           127:        return (Z_TYPE_P( z1 ) == Z_TYPE_PP( z2 ) && 
        !           128:             Z_TYPE_P( z1 ) == IS_RESOURCE     &&
        !           129:             Z_LVAL_P( z1 ) == Z_LVAL_PP( z2 ) );
        !           130: }
        !           131: /* }}} */
        !           132: 
        !           133: /* {{{ proto int curl_multi_remove_handle(resource mh, resource ch)
        !           134:    Remove a multi handle from a set of cURL handles */
        !           135: PHP_FUNCTION(curl_multi_remove_handle)
        !           136: {
        !           137:        zval      *z_mh;
        !           138:        zval      *z_ch;
        !           139:        php_curlm *mh;
        !           140:        php_curl  *ch;
        !           141: 
        !           142:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &z_mh, &z_ch) == FAILURE) {
        !           143:                return;
        !           144:        }
        !           145: 
        !           146:        ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
        !           147:        ZEND_FETCH_RESOURCE(ch, php_curl *, &z_ch, -1, le_curl_name, le_curl);
        !           148: 
        !           149:        --ch->uses;
        !           150: 
        !           151:        zend_llist_del_element( &mh->easyh, &z_ch, 
        !           152:                                                        (int (*)(void *, void *)) curl_compare_resources );
        !           153:        
        !           154:        RETURN_LONG((long) curl_multi_remove_handle(mh->multi, ch->cp));
        !           155: }
        !           156: /* }}} */
        !           157: 
        !           158: static void _make_timeval_struct(struct timeval *to, double timeout) /* {{{ */
        !           159: {
        !           160:        unsigned long conv;
        !           161: 
        !           162:        conv = (unsigned long) (timeout * 1000000.0);
        !           163:        to->tv_sec = conv / 1000000;
        !           164:        to->tv_usec = conv % 1000000;
        !           165: }
        !           166: /* }}} */
        !           167: 
        !           168: /* {{{ proto int curl_multi_select(resource mh[, double timeout])
        !           169:    Get all the sockets associated with the cURL extension, which can then be "selected" */
        !           170: PHP_FUNCTION(curl_multi_select)
        !           171: {
        !           172:        zval           *z_mh;
        !           173:        php_curlm      *mh;
        !           174:        fd_set          readfds;
        !           175:        fd_set          writefds;
        !           176:        fd_set          exceptfds;
        !           177:        int             maxfd;
        !           178:        double          timeout = 1.0;
        !           179:        struct timeval  to;
        !           180: 
        !           181:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|d", &z_mh, &timeout) == FAILURE) {
        !           182:                return;
        !           183:        }
        !           184: 
        !           185:        ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
        !           186: 
        !           187:        _make_timeval_struct(&to, timeout);
        !           188:        
        !           189:        FD_ZERO(&readfds);
        !           190:        FD_ZERO(&writefds);
        !           191:        FD_ZERO(&exceptfds);
        !           192: 
        !           193:        curl_multi_fdset(mh->multi, &readfds, &writefds, &exceptfds, &maxfd);
        !           194:        RETURN_LONG(select(maxfd + 1, &readfds, &writefds, &exceptfds, &to));
        !           195: }
        !           196: /* }}} */
        !           197: 
        !           198: /* {{{ proto int curl_multi_exec(resource mh, int &still_running) 
        !           199:    Run the sub-connections of the current cURL handle */
        !           200: PHP_FUNCTION(curl_multi_exec)
        !           201: {
        !           202:        zval      *z_mh;
        !           203:        zval      *z_still_running;
        !           204:        php_curlm *mh;
        !           205:        int        still_running;
        !           206:        int        result;
        !           207: 
        !           208:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &z_mh, &z_still_running) == FAILURE) {
        !           209:                return;
        !           210:        }
        !           211: 
        !           212:        ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
        !           213: 
        !           214:        {
        !           215:                zend_llist_position pos;
        !           216:                php_curl *ch;
        !           217:                zval    *pz_ch;
        !           218: 
        !           219:                for(pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch;
        !           220:                        pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) {
        !           221: 
        !           222:                        ZEND_FETCH_RESOURCE(ch, php_curl *, &pz_ch, -1, le_curl_name, le_curl);
        !           223:                        _php_curl_verify_handlers(ch, 1 TSRMLS_CC);
        !           224:                }
        !           225:        }
        !           226: 
        !           227:        convert_to_long_ex(&z_still_running);
        !           228:        still_running = Z_LVAL_P(z_still_running);
        !           229:        result = curl_multi_perform(mh->multi, &still_running);
        !           230:        ZVAL_LONG(z_still_running, still_running);
        !           231: 
        !           232:        RETURN_LONG(result);
        !           233: }
        !           234: /* }}} */
        !           235: 
        !           236: /* {{{ proto string curl_multi_getcontent(resource ch)
        !           237:    Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set */
        !           238: PHP_FUNCTION(curl_multi_getcontent)
        !           239: {
        !           240:        zval     *z_ch;
        !           241:        php_curl *ch;
        !           242: 
        !           243:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ch) == FAILURE) {
        !           244:                return;
        !           245:        }
        !           246: 
        !           247:        ZEND_FETCH_RESOURCE(ch, php_curl *, &z_ch, -1, le_curl_name, le_curl);
        !           248: 
        !           249:        if (ch->handlers->write->method == PHP_CURL_RETURN && ch->handlers->write->buf.len > 0) {
        !           250:                smart_str_0(&ch->handlers->write->buf);
        !           251:                RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 1);
        !           252:        }
        !           253: }
        !           254: /* }}} */
        !           255: 
        !           256: /* {{{ proto array curl_multi_info_read(resource mh [, long msgs_in_queue])
        !           257:    Get information about the current transfers */
        !           258: PHP_FUNCTION(curl_multi_info_read)
        !           259: {
        !           260:        zval      *z_mh;
        !           261:        php_curlm *mh;
        !           262:        CURLMsg   *tmp_msg;
        !           263:        int        queued_msgs;
        !           264:        zval      *zmsgs_in_queue = NULL;
        !           265: 
        !           266:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|z", &z_mh, &zmsgs_in_queue) == FAILURE) {
        !           267:                return;
        !           268:        }
        !           269: 
        !           270:        ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
        !           271: 
        !           272:        tmp_msg = curl_multi_info_read(mh->multi, &queued_msgs);
        !           273:        if (tmp_msg == NULL) {
        !           274:                RETURN_FALSE;
        !           275:        }
        !           276:        if (zmsgs_in_queue) {
        !           277:                zval_dtor(zmsgs_in_queue);
        !           278:                ZVAL_LONG(zmsgs_in_queue, queued_msgs);
        !           279:        }
        !           280: 
        !           281:        array_init(return_value);
        !           282:        add_assoc_long(return_value, "msg", tmp_msg->msg);
        !           283:        add_assoc_long(return_value, "result", tmp_msg->data.result);
        !           284: 
        !           285:        /* find the original easy curl handle */
        !           286:        {
        !           287:                zend_llist_position pos;
        !           288:                php_curl *ch;
        !           289:                zval    *pz_ch;
        !           290: 
        !           291:                /* search the list of easy handles hanging off the multi-handle */
        !           292:                for(pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch;
        !           293:                        pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) {
        !           294:                        ZEND_FETCH_RESOURCE(ch, php_curl *, &pz_ch, -1, le_curl_name, le_curl);
        !           295:                        if (ch->cp == tmp_msg->easy_handle) {
        !           296: 
        !           297:                                /* we are adding a reference to the underlying php_curl
        !           298:                                   resource, so we need to add one to the resource's refcount 
        !           299:                                   in order to ensure it doesn't get destroyed when the 
        !           300:                                   underlying curl easy handle goes out of scope.
        !           301:                                   Normally you would call zval_copy_ctor( pz_ch ), or
        !           302:                                   SEPARATE_ZVAL, but those create new zvals, which is already
        !           303:                                   being done in add_assoc_resource */
        !           304: 
        !           305:                                zend_list_addref( Z_RESVAL_P( pz_ch ) );
        !           306: 
        !           307:                                /* add_assoc_resource automatically creates a new zval to 
        !           308:                                   wrap the "resource" represented by the current pz_ch */
        !           309: 
        !           310:                                add_assoc_resource(return_value, "handle", Z_RESVAL_P(pz_ch));
        !           311: 
        !           312:                                break;
        !           313:                        }
        !           314:                }
        !           315:        }
        !           316: }
        !           317: /* }}} */
        !           318: 
        !           319: /* {{{ proto void curl_multi_close(resource mh)
        !           320:    Close a set of cURL handles */
        !           321: PHP_FUNCTION(curl_multi_close)
        !           322: {
        !           323:        zval      *z_mh;
        !           324:        php_curlm *mh;
        !           325: 
        !           326:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_mh) == FAILURE) {
        !           327:                return;
        !           328:        }
        !           329: 
        !           330:        ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
        !           331: 
        !           332:        zend_list_delete(Z_LVAL_P(z_mh));
        !           333: }
        !           334: /* }}} */
        !           335: 
        !           336: void _php_curl_multi_close(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
        !           337: {
        !           338:        php_curlm *mh = (php_curlm *) rsrc->ptr;
        !           339:        if (mh) {
        !           340:                zend_llist_position pos;
        !           341:                php_curl *ch;
        !           342:                zval    *pz_ch;
        !           343: 
        !           344:                for(pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch;
        !           345:                        pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) {
        !           346: 
        !           347:                        ch = (php_curl *) zend_fetch_resource(&pz_ch TSRMLS_CC, -1, le_curl_name, NULL, 1, le_curl);
        !           348:                        _php_curl_verify_handlers(ch, 0 TSRMLS_CC);
        !           349:                }
        !           350: 
        !           351:                curl_multi_cleanup(mh->multi);
        !           352:                zend_llist_clean(&mh->easyh);
        !           353:                efree(mh);
        !           354:                rsrc->ptr = NULL;
        !           355:        }
        !           356: }
        !           357: /* }}} */
        !           358: 
        !           359: #endif
        !           360: 
        !           361: /*
        !           362:  * Local variables:
        !           363:  * tab-width: 4
        !           364:  * c-basic-offset: 4
        !           365:  * End:
        !           366:  * vim600: noet sw=4 ts=4 fdm=marker
        !           367:  * vim<600: noet sw=4 ts=4
        !           368:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>