X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-ares;a=blobdiff_plain;f=php_ares.c;h=08dc1d3830fc39e51ad98a5720674ab6b5163cad;hp=54b0f4cbbd2bf2517eb6d2f89e2b6e6bd24708ff;hb=e3bfd5ac45be7d929f95ecd4530183e9ac07cc1f;hpb=d200b6a8f6372b2954d330f46dc6814377defe74 diff --git a/php_ares.c b/php_ares.c index 54b0f4c..08dc1d3 100644 --- a/php_ares.c +++ b/php_ares.c @@ -18,6 +18,7 @@ #include "php.h" #include "php_ini.h" +#include "php_streams.h" #include "ext/standard/info.h" #include "php_ares.h" @@ -174,6 +175,18 @@ static const char *php_ares_T_names[] = { #define PHP_ARES_QUERY_BUFFER_LEN 2<<0xf +#ifdef HAVE_ARES_INET_PTON +# define inet_pton ares_inet_pton_wrapper +static inline int ares_inet_pton_wrapper(int af, const void *src, char *dst, socklen_t size) +{ + return dst == ares_inet_pton(af, src, dst, size); +} +#endif + +#ifdef HAVE_ARES_INET_NTOP +# define inet_ntop ares_inet_ntop +#endif + /* {{{ typedefs */ typedef struct _php_ares_options { struct ares_options strct; @@ -573,7 +586,7 @@ local php_ares_options *php_ares_options_ctor(php_ares_options *options, HashTab SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(opt), (void *) &entry); zend_hash_move_forward(Z_ARRVAL_PP(opt))) { if (Z_TYPE_PP(entry) == IS_STRING) { - inet_aton(Z_STRVAL_PP(entry), &options->strct.servers[options->strct.nservers++]); + inet_pton(AF_INET, Z_STRVAL_PP(entry), &options->strct.servers[options->strct.nservers++]); } } if (options->strct.nservers) { @@ -686,7 +699,7 @@ local int php_ares_parse(const unsigned char *abuf, int alen, zval *result TSRML for (answer_count = ntohs(header->ancount); answer_count-- && pointer < (abuf + alen); ) { uint16_t stmp, type, class; uint32_t ltmp, ttl; - zval **entry_ptr, *entry = NULL; + zval *entry = NULL; if (0 > (byte_count = php_ares_skip(pointer, abuf, alen TSRMLS_CC))) { return FAILURE; @@ -709,10 +722,19 @@ local int php_ares_parse(const unsigned char *abuf, int alen, zval *result TSRML #endif switch (type) { case T_A: - spprintf(&name, 0, "%d.%d.%d.%d", pointer[0], pointer[1], pointer[2], pointer[3]); + name = ecalloc(1, 16); + inet_ntop(AF_INET, pointer, name, 16); add_assoc_string(entry, "addr", name, 0); pointer += byte_count; break; +#ifdef T_AAAA + case T_AAAA: + name = ecalloc(1, 48); + inet_ntop(AF_INET6, pointer, name, 48); + add_assoc_string(entry, "addr", name, 0); + pointer += byte_count; + break; +#endif case T_NS: case T_PTR: @@ -795,6 +817,9 @@ local int php_ares_parse(const unsigned char *abuf, int alen, zval *result TSRML break; default: +#ifndef HAVE_INET_PTON + skip: +#endif zval_ptr_dtor(&entry); entry = NULL; pointer += byte_count; @@ -824,7 +849,7 @@ static void php_ares_callback_func_old(void *aq, int status, unsigned char *abuf MAKE_STD_ZVAL(parsed); ZVAL_NULL(parsed); - if (SUCCESS == php_ares_parse(abuf, alen, parsed)) { + if (SUCCESS == php_ares_parse(abuf, alen, parsed TSRMLS_CC)) { q->result.std.arr = parsed; } else { zval_ptr_dtor(&parsed); @@ -1011,13 +1036,19 @@ local int php_ares_process(php_ares *ares, long max_timeout) /* {{{ */ } /* }}} */ -local int php_ares_publish_fds(fd_set *R, fd_set *W, zval *r, zval *w) /* {{{ */ +local int php_ares_publish_fds(fd_set *R, fd_set *W, zval *r, zval *w, HashTable *resource_map) /* {{{ */ { int i, nfds = 0; + zval **fd; for (i = 0; i < FD_SETSIZE; ++i) { if (FD_ISSET(i, R)) { - add_next_index_long(r, i); + if (resource_map && (SUCCESS == zend_hash_index_find(resource_map, i, (void *) &fd))) { + zval_add_ref(fd); + add_next_index_zval(r, *fd); + } else { + add_next_index_long(r, i); + } if (i > nfds) { nfds = i; } @@ -1026,7 +1057,12 @@ local int php_ares_publish_fds(fd_set *R, fd_set *W, zval *r, zval *w) /* {{{ */ for (i = 0; i < FD_SETSIZE; ++i) { if (FD_ISSET(i, W)) { - add_next_index_long(w, i); + if (resource_map && (SUCCESS == zend_hash_index_find(resource_map, i, (void *) &fd))) { + zval_add_ref(fd); + add_next_index_zval(r, *fd); + } else { + add_next_index_long(w, i); + } if (i > nfds) { nfds = i; } @@ -1037,16 +1073,33 @@ local int php_ares_publish_fds(fd_set *R, fd_set *W, zval *r, zval *w) /* {{{ */ } /* }}} */ -local int php_ares_extract_fds(zval *r, zval *w, fd_set *R, fd_set *W) /* {{{ */ +local int php_ares_extract_fds(zval *r, zval *w, fd_set *R, fd_set *W, HashTable *resource_map TSRMLS_DC) /* {{{ */ { zval **fd; int nfds = 0; + zval zmap; + INIT_ZVAL(zmap); + Z_ARRVAL(zmap) = resource_map; + Z_TYPE(zmap) = IS_ARRAY; if (r && zend_hash_num_elements(Z_ARRVAL_P(r))) { for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(r)); SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(r), (void *) &fd); zend_hash_move_forward(Z_ARRVAL_P(r))) { - if (Z_TYPE_PP(fd) == IS_LONG) { + if (Z_TYPE_PP(fd) == IS_RESOURCE) { + php_stream *s = NULL; + int id = 0; + + ZEND_FETCH_RESOURCE_NO_RETURN(s, php_stream *, fd, -1, NULL, php_file_le_stream()); + if (s && (SUCCESS == php_stream_cast(s, PHP_STREAM_AS_FD_FOR_SELECT, (void *) &id, 1))) { + zval_add_ref(fd); + add_index_zval(&zmap, id, *fd); + FD_SET(id, R); + if (id > nfds) { + nfds = id; + } + } + } else if (Z_TYPE_PP(fd) == IS_LONG) { FD_SET(Z_LVAL_PP(fd), R); if (Z_LVAL_PP(fd) > nfds) { nfds = Z_LVAL_PP(fd); @@ -1059,7 +1112,20 @@ local int php_ares_extract_fds(zval *r, zval *w, fd_set *R, fd_set *W) /* {{{ */ for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(w)); SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(w), (void *) &fd); zend_hash_move_forward(Z_ARRVAL_P(w))) { - if (Z_TYPE_PP(fd) == IS_LONG) { + if (Z_TYPE_PP(fd) == IS_RESOURCE) { + php_stream *s = NULL; + int id = 0; + + ZEND_FETCH_RESOURCE_NO_RETURN(s, php_stream *, fd, -1, NULL, php_file_le_stream()); + if (s && (SUCCESS == php_stream_cast(s, PHP_STREAM_AS_FD_FOR_SELECT, (void *) &id, 1))) { + zval_add_ref(fd); + add_index_zval(&zmap, id, *fd); + FD_SET(id, W); + if (id > nfds) { + nfds = id; + } + } + } else if (Z_TYPE_PP(fd) == IS_LONG) { FD_SET(Z_LVAL_PP(fd), W); if (Z_LVAL_PP(fd) > nfds) { nfds = Z_LVAL_PP(fd); @@ -1665,7 +1731,7 @@ static PHP_FUNCTION(ares_process) FD_ZERO(&R); FD_ZERO(&W); - php_ares_extract_fds(read, write, &R, &W); + php_ares_extract_fds(read, write, &R, &W, NULL TSRMLS_CC); ares_process(ares->channel, &R, &W); } /* }}} */ @@ -1679,6 +1745,7 @@ static PHP_FUNCTION(ares_select) int nfds; long timeout; struct timeval tv; + HashTable resource_map; if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aal", &read, &write, &timeout)) { RETURN_FALSE; @@ -1695,14 +1762,17 @@ static PHP_FUNCTION(ares_select) FD_ZERO(&R); FD_ZERO(&W); - nfds = php_ares_extract_fds(read, write, &R, &W); + zend_hash_init(&resource_map, zend_hash_num_elements(Z_ARRVAL_P(read) + zend_hash_num_elements(Z_ARRVAL_P(write))), NULL, ZVAL_PTR_DTOR, 0); + nfds = php_ares_extract_fds(read, write, &R, &W, &resource_map TSRMLS_CC); if (-1 < select(nfds, &R, &W, NULL, &tv)) { zend_hash_clean(Z_ARRVAL_P(read)); zend_hash_clean(Z_ARRVAL_P(write)); - php_ares_publish_fds(&R, &W, read, write); - RETURN_TRUE; + php_ares_publish_fds(&R, &W, read, write, &resource_map); + RETVAL_TRUE; + } else { + RETVAL_FALSE; } - RETURN_FALSE; + zend_hash_destroy(&resource_map); } /* }}} */ @@ -1748,7 +1818,7 @@ static PHP_FUNCTION(ares_fds) array_init(read); array_init(write); ares_fds(ares->channel, &R, &W); - RETVAL_LONG(php_ares_publish_fds(&R, &W, read, write)); + RETVAL_LONG(php_ares_publish_fds(&R, &W, read, write, NULL)); } /* }}} */