From: Michael Wallner Date: Fri, 1 Aug 2014 11:41:04 +0000 (+0200) Subject: build robustness X-Git-Tag: RELEASE_0_8_0~18 X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-ares;a=commitdiff_plain;h=9adb0865a7247e7299d0e8e675802782925253a2 build robustness --- diff --git a/ares.c b/ares.c deleted file mode 100644 index 7191268..0000000 --- a/ares.c +++ /dev/null @@ -1,2044 +0,0 @@ -/* - +--------------------------------------------------------------------+ - | PECL :: ares | - +--------------------------------------------------------------------+ - | Redistribution and use in source and binary forms, with or without | - | modification, are permitted provided that the conditions mentioned | - | in the accompanying LICENSE file are met. | - +--------------------------------------------------------------------+ - | Copyright (c) 2006, Michael Wallner | - +--------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "php_ares.h" - -#include -#ifdef HAVE_ARES_VERSION -# include -#endif -#ifdef HAVE_NETDB_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_ARPA_INET_H -# include -#endif -#ifdef HAVE_ARPA_NAMESER_H -# include -#endif -#ifdef HAVE_ARPA_NAMESER_COMPAT_H -# include -#endif - -#define local inline - -#ifndef ZEND_ENGINE_2 -# define IS_CALLABLE(a,b,c) 1 -# ifndef ZTS -# undef TSRMLS_SET_CTX -# define TSRMLS_SET_CTX -# undef TSRMLS_FETCH_FROM_CTX -# define TSRMLS_FETCH_FROM_CTX -# endif -#endif -#if (PHP_MAJOR_VERSION > 5) || ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3)) -# define ADDREF(z) Z_ADDREF_P(z) -# define IS_CALLABLE(a,b,c) zend_is_callable((a), (b), (c) TSRMLS_CC) -#else -# define ADDREF(z) ZVAL_ADDREF(z) -# define IS_CALLABLE(a,b,c) zend_is_callable((a), (b), (c)) -#endif - -#define PHP_ARES_LE_NAME "AsyncResolver" -#define PHP_ARES_QUERY_LE_NAME "AsyncResolverQuery" -static int le_ares; -static int le_ares_query; - -static const char *php_ares_C_names[] = { - "INVALID", - "IN", - "CHAOS", - "HS", - "NONE", - "ANY", -}; - -static const char *php_ares_T_names[] = { - "INVALID", - "A", - "NS", - "MD", - "MF", - "CNAME", - "SOA", - "MB", - "MG", - "MR", - "NULL", - "WKS", - "PTR", - "HINFO", - "MINFO", - "MX", - "TXT", - "RP", - "AFSDB", - "X25", - "ISDN", - "RT", - "NSAP", - "NSAP_PTR", - "SIG", - "KEY", - "PX", - "GPOS", - "AAAA", - "LOC", - "NXT", - "EID", - "NIMLOC", - "SRV", - "ATMA", - "NAPTR", - "KX", - "CERT", - "A6", - "DNAME", - "SINK", - "OPT", - "APL", - "TKEY", - "TSIG", - "IXFR", - "AXFR", - "MAILB", - "MAILA", - "ANY", - "ZXFR", -}; - -#ifdef HAVE_OLD_ARES_STRERROR -# define PHP_ARES_ERROR(err) { \ - char *__tmp = NULL; \ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ares_strerror(err, &__tmp)); \ - if (__tmp) ares_free_errmem(__tmp); \ -} -#else -# define PHP_ARES_ERROR(err) \ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ares_strerror(err)) -#endif - -#define RETURN_ARES_ERROR(err) \ - PHP_ARES_ERROR(err); \ - RETURN_FALSE -#define PHP_ARES_CB_ERROR(param) \ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected the " param " argument to be a valid callback") -#define RETURN_ARES_CB_ERROR(param) \ - PHP_ARES_CB_ERROR(param); \ - RETURN_FALSE - -#define PHP_ARES_QUERY_BUFFER_LEN 2<<0xf - -/* {{{ typedefs */ -typedef struct _php_ares_options { - struct ares_options strct; - int flags; -} php_ares_options; - -typedef struct _php_ares { - ares_channel channel; - php_ares_options options; - zend_llist queries; - void ***tsrm_ls; - unsigned in_callback:1; - unsigned reserved:31; -} php_ares; - -typedef enum _php_ares_query_type { - PHP_ARES_CB_STD, - PHP_ARES_CB_HOST, - PHP_ARES_CB_NINFO, -} php_ares_query_type; - -typedef enum _php_ares_query_packet_type { - PHP_ARES_PCKT_SEARCH, - PHP_ARES_PCKT_QUERY, - PHP_ARES_PCKT_SEND, - PHP_ARES_PCKT_HNAME, - PHP_ARES_PCKT_HADDR, - PHP_ARES_PCKT_NINFO, -} php_ares_query_packet_type; - -typedef union _php_ares_query_packet_data { - struct { - char *name; - int name_len; - long type; - long dnsclass; - } search; - struct { - char *name; - int name_len; - long type; - long dnsclass; - } query; - struct { - char *buf; - int len; - } send; - struct { - char *name; - int name_len; - long family; - } hname; - struct { - char *addr; - int addr_len; - long family; - } haddr; - struct { - char *addr; - int addr_len; - long port; - long family; - long flags; - } ninfo; -} php_ares_query_packet_data; - -typedef struct _php_ares_query_packet { - php_ares_query_packet_type type; - php_ares_query_packet_data data; -} php_ares_query_packet; - -typedef union _php_ares_query_result { - struct { - zval *arr; - char *buf; - int len; - } std; - struct hostent host; - struct { - char *service; - char *node; - } ninfo; -} php_ares_query_result; - -typedef struct _php_ares_query { - int id; - int error; - php_ares *ares; - zval *callback; - php_ares_query_type type; - php_ares_query_packet packet; - php_ares_query_result result; -} php_ares_query; -/* }}} */ - -local struct hostent *php_ares_hostent_ctor(struct hostent *host) /* {{{ */ -{ - if (!host) { - host = emalloc(sizeof(struct hostent)); - } - memset(host, 0, sizeof(struct hostent)); - - return host; -} -/* }}} */ - -local void php_ares_hostent_copy(struct hostent *from, struct hostent *to) /* {{{ */ -{ - int i, c; - char **ptr; - - memcpy(to, from, sizeof(struct hostent)); - to->h_name = estrdup(from->h_name); - for (c = 0, ptr = from->h_aliases; *ptr; ++ptr, ++c); - to->h_aliases = ecalloc((c+1), sizeof(char *)); - for (i = 0; i < c; ++i) { - to->h_aliases[i] = estrdup(from->h_aliases[i]); - } - for (c = 0, ptr = from->h_addr_list; *ptr; ++ptr, ++c); - to->h_addr_list = ecalloc((c+1), sizeof(char *)); - for (i = 0; i < c; ++i) { - to->h_addr_list[i] = emalloc(from->h_length); - memcpy(to->h_addr_list[i], from->h_addr_list[i], from->h_length); - } -} -/* }}} */ - -local void php_ares_hostent_to_struct(struct hostent *hostent, HashTable *ht) /* {{{ */ -{ - zval array, *tmp; - char **ptr; - - INIT_PZVAL(&array); - Z_TYPE(array) = IS_ARRAY; - Z_ARRVAL(array) = ht; - - if (hostent) { - add_assoc_string(&array, "name", hostent->h_name, 1); - - MAKE_STD_ZVAL(tmp); - array_init(tmp); - if (hostent->h_aliases) { - for (ptr = hostent->h_aliases; *ptr; ++ptr) { - add_next_index_string(tmp, *ptr, 1); - } - } - add_assoc_zval(&array, "aliases", tmp); - add_assoc_long(&array, "addrtype", hostent->h_addrtype); - - MAKE_STD_ZVAL(tmp); - array_init(tmp); - if (hostent->h_addr_list) { - for (ptr = hostent->h_addr_list; *ptr; ++ptr) { - char name[64] = {0}; - - if (inet_ntop(hostent->h_addrtype, *ptr, name, sizeof(name)-1)) { - add_next_index_string(tmp, name, 1); - } - } - } - add_assoc_zval(&array, "addrlist", tmp); - } -} -/* }}} */ - -local void php_ares_hostent_dtor(struct hostent *host) /* {{{ */ -{ - char **ptr; - - STR_FREE(host->h_name); - if (host->h_aliases) { - for (ptr = host->h_aliases; *ptr; ++ptr) { - efree(*ptr); - } - efree(host->h_aliases); - } - if (host->h_addr_list) { - for (ptr = host->h_addr_list; *ptr; ++ptr) { - efree(*ptr); - } - efree(host->h_addr_list); - } - memset(host, 0, sizeof(struct hostent)); -} -/* }}} */ - -local void php_ares_hostent_free(struct hostent **host) /* {{{ */ -{ - php_ares_hostent_dtor(*host); - efree(*host); - *host = NULL; -} -/* }}} */ - -local php_ares_query *php_ares_query_ctor(php_ares_query *query, php_ares_query_type type, php_ares *ares, zval *callback) /* {{{ */ -{ - if (!query) { - query = emalloc(sizeof(php_ares_query)); - } - memset(query, 0, sizeof(php_ares_query)); - - query->ares = ares; - query->type = type; - query->error = -1; - - if (callback) { - ADDREF(callback); - query->callback = callback; - } - - return query; -} -/* }}} */ - -local void php_ares_query_rsrc(php_ares_query *query, zval *return_value) /* {{{ */ -{ - TSRMLS_FETCH_FROM_CTX(query->ares->tsrm_ls); - - ZEND_REGISTER_RESOURCE(return_value, query, le_ares_query); - query->id = Z_LVAL_P(return_value); - zend_list_addref(query->id); - zend_llist_add_element(&query->ares->queries, &query); -} -/* }}} */ - -local void php_ares_query_pckt(php_ares_query *query, php_ares_query_packet_type type, ...) -{ - va_list argv; - char *buf; - int len; - - va_start(argv, type); - - switch (query->packet.type = type) { - case PHP_ARES_PCKT_SEARCH: - buf = va_arg(argv, char *); - len = va_arg(argv, int); - query->packet.data.search.name = estrndup(buf, len); - query->packet.data.search.name_len = len; - query->packet.data.search.type = va_arg(argv, long); - query->packet.data.search.dnsclass = va_arg(argv, long); - break; - - case PHP_ARES_PCKT_QUERY: - buf = va_arg(argv, char *); - len = va_arg(argv, int); - query->packet.data.query.name = estrndup(buf, len); - query->packet.data.query.name_len = len; - query->packet.data.query.type = va_arg(argv, long); - query->packet.data.query.dnsclass = va_arg(argv, long); - break; - - case PHP_ARES_PCKT_SEND: - buf = va_arg(argv, char *); - len = va_arg(argv, int); - query->packet.data.send.buf = estrndup(buf, len); - query->packet.data.send.len = len; - break; - - case PHP_ARES_PCKT_HNAME: - buf = va_arg(argv, char *); - len = va_arg(argv, int); - query->packet.data.hname.name = estrndup(buf, len); - query->packet.data.hname.name_len = len; - query->packet.data.hname.family = va_arg(argv, long); - break; - - case PHP_ARES_PCKT_HADDR: - buf = va_arg(argv, char *); - len = va_arg(argv, int); - query->packet.data.haddr.addr = estrndup(buf, len); - query->packet.data.haddr.addr_len = len; - query->packet.data.haddr.family = va_arg(argv, long); - break; - - case PHP_ARES_PCKT_NINFO: - query->packet.data.ninfo.flags = va_arg(argv, long); - buf = va_arg(argv, char *); - len = va_arg(argv, int); - query->packet.data.ninfo.addr = estrndup(buf, len); - query->packet.data.ninfo.addr_len = len; - query->packet.data.ninfo.family = va_arg(argv, long); - query->packet.data.ninfo.port = va_arg(argv, long); - break; - } - - va_end(argv); -} - -local void php_ares_query_dtor(php_ares_query *query) /* {{{ */ -{ - struct php_ares_query_packet_buf {char *buf;} *packet; - - packet = (struct php_ares_query_packet_buf *) &query->packet.data; - if (packet->buf) { - efree(packet->buf); - } - switch (query->type) { - case PHP_ARES_CB_STD: - if (query->result.std.arr) { - zval_ptr_dtor(&query->result.std.arr); - } - STR_FREE(query->result.std.buf); - break; - case PHP_ARES_CB_HOST: - php_ares_hostent_dtor(&query->result.host); - break; - case PHP_ARES_CB_NINFO: - STR_FREE(query->result.ninfo.service); - STR_FREE(query->result.ninfo.node); - break; - } - if (query->callback) { - zval_ptr_dtor(&query->callback); - } - memset(query, 0, sizeof(php_ares_query)); -} -/* }}} */ - -local void php_ares_query_free(php_ares_query **query) /* {{{ */ -{ - php_ares_query_dtor(*query); - efree(*query); - *query = NULL; -} -/* }}} */ - -local php_ares_options *php_ares_options_ctor(php_ares_options *options, HashTable *ht) /* {{{ */ -{ - int i; - zval **opt, **entry; - - if (!options) { - options = emalloc(sizeof(php_ares_options)); - } - memset(options, 0, sizeof(php_ares_options)); - - if (ht && zend_hash_num_elements(ht)) { - if ((SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) { - options->flags |= ARES_OPT_FLAGS; - options->strct.flags = Z_LVAL_PP(opt); - } - if ((SUCCESS == zend_hash_find(ht, "timeout", sizeof("timeout"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) { - options->flags |= ARES_OPT_TIMEOUT; - options->strct.timeout = Z_LVAL_PP(opt); - } - if ((SUCCESS == zend_hash_find(ht, "tries", sizeof("tries"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) { - options->flags |= ARES_OPT_TRIES; - options->strct.tries = Z_LVAL_PP(opt); - } - if ((SUCCESS == zend_hash_find(ht, "ndots", sizeof("ndots"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) { - options->flags |= ARES_OPT_NDOTS; - options->strct.ndots = Z_LVAL_PP(opt); - } - if ((SUCCESS == zend_hash_find(ht, "udp_port", sizeof("udp_port"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) { - options->flags |= ARES_OPT_UDP_PORT; - options->strct.udp_port = htons((unsigned short) Z_LVAL_PP(opt)); - } - if ((SUCCESS == zend_hash_find(ht, "tcp_port", sizeof("tcp_port"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) { - options->flags |= ARES_OPT_TCP_PORT; - options->strct.tcp_port = htons((unsigned short) Z_LVAL_PP(opt)); - } - if ((SUCCESS == zend_hash_find(ht, "servers", sizeof("servers"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_ARRAY) && (i = zend_hash_num_elements(Z_ARRVAL_PP(opt)))) { - options->strct.servers = ecalloc(i, sizeof(struct in_addr)); - for ( zend_hash_internal_pointer_reset(Z_ARRVAL_PP(opt)); - 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++]); - } - } - if (options->strct.nservers) { - options->flags |= ARES_OPT_SERVERS; - } - } - if ((SUCCESS == zend_hash_find(ht, "domains", sizeof("domains"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_ARRAY) && (i = zend_hash_num_elements(Z_ARRVAL_PP(opt)))) { - options->strct.domains = ecalloc(i, sizeof(char *)); - for ( zend_hash_internal_pointer_reset(Z_ARRVAL_PP(opt)); - 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) { - options->strct.domains[options->strct.ndomains++] = estrdup(Z_STRVAL_PP(entry)); - } - } - if (options->strct.ndomains) { - options->flags |= ARES_OPT_DOMAINS; - } - } - if ((SUCCESS == zend_hash_find(ht, "lookups", sizeof("lookups"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_STRING)) { - options->flags |= ARES_OPT_LOOKUPS; - options->strct.lookups = estrdup(Z_STRVAL_PP(opt)); - } - } - - return options; -} -/* }}} */ - -local void php_ares_options_dtor(php_ares_options *options) /* {{{ */ -{ - int i; - - if (options->strct.servers) { - efree(options->strct.servers); - } - - if (options->strct.domains) { - for (i = 0; i < options->strct.ndomains; ++i) { - efree(options->strct.domains[i]); - } - efree(options->strct.domains); - } - - STR_FREE(options->strct.lookups); - - memset(options, 0, sizeof(php_ares_options)); -} -/* }}} */ - -local void php_ares_options_free(php_ares_options **options) /* {{{ */ -{ - php_ares_options_dtor(*options); - efree(*options); - *options = NULL; -} -/* }}} */ - -local PHP_ARES_EXPAND_LEN_TYPE php_ares_skip(const unsigned char *pointer, const unsigned char *abuf, int alen TSRMLS_DC) -{ - char *name; - int rc; - PHP_ARES_EXPAND_LEN_TYPE byte_count; - - /* NOTE: byte_count is not neccessarily the length of the string, - i.e. if there were back references */ - if (ARES_SUCCESS == (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) { - /*fprintf(stderr, "-- skipping %s\n", name);*/ - ares_free_string(name); - return byte_count; - } - PHP_ARES_ERROR(rc); - return -1; -} - -local int php_ares_parse(const unsigned char *abuf, int alen, zval *result TSRMLS_DC) /* {{{ */ -{ - HEADER *header; - PHP_ARES_EXPAND_LEN_TYPE byte_count; - const unsigned char *pointer; - char *name; - int rc, query_count, answer_count; - - convert_to_array(result); - - if (!alen || !abuf || !*abuf) { - return SUCCESS; - } - - header = (HEADER *) abuf; - pointer = abuf + HFIXEDSZ; - - for (query_count = ntohs(header->qdcount); query_count--; pointer += byte_count + QFIXEDSZ) { - if (0 > (byte_count = php_ares_skip(pointer, abuf, alen TSRMLS_CC))) { - return FAILURE; - } - } - - 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; - - if (0 > (byte_count = php_ares_skip(pointer, abuf, alen TSRMLS_CC))) { - return FAILURE; - } - - pointer += byte_count; - - MAKE_STD_ZVAL(entry); - array_init(entry); - - GETSHORT(type, pointer); - add_assoc_string(entry, "type", estrdup(php_ares_T_names[type]), 0); - GETSHORT(class, pointer); - add_assoc_string(entry, "class", estrdup(php_ares_C_names[class]), 0); - GETLONG(ttl, pointer); - add_assoc_long(entry, "ttl", ttl); - GETSHORT(byte_count, pointer); -#if 0 - fprintf(stderr, ">> processing %s answer of length %d\n", php_ares_T_names[type], byte_count); -#endif - switch (type) { - case T_A: - spprintf(&name, 0, "%d.%d.%d.%d", pointer[0], pointer[1], pointer[2], pointer[3]); - add_assoc_string(entry, "addr", name, 0); - pointer += byte_count; - break; - - case T_NS: - case T_PTR: - case T_CNAME: - if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) { - PHP_ARES_ERROR(rc); - return FAILURE; - } - pointer += byte_count; - add_assoc_string(entry, "name", name, 1); - ares_free_string(name); - break; - - case T_MX: - GETSHORT(stmp, pointer); - if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) { - PHP_ARES_ERROR(rc); - return FAILURE; - } - pointer += byte_count; - add_assoc_long(entry, "weight", stmp); - add_assoc_string(entry, "name", name, 1); - ares_free_string(name); - break; - - case T_SRV: - GETSHORT(stmp, pointer); - add_assoc_long(entry, "priority", stmp); - GETSHORT(stmp, pointer); - add_assoc_long(entry, "weight", stmp); - GETSHORT(stmp, pointer); - add_assoc_long(entry, "port", stmp); - - if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) { - PHP_ARES_ERROR(rc); - zval_ptr_dtor(&entry); - return FAILURE; - } - pointer += byte_count; - add_assoc_string(entry, "name", name, 1); - ares_free_string(name); - break; - - case T_SOA: - if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) { - PHP_ARES_ERROR(rc); - zval_ptr_dtor(&entry); - return FAILURE; - } - pointer += byte_count; - add_assoc_string(entry, "name", name, 1); - ares_free_string(name); - - if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) { - PHP_ARES_ERROR(rc); - zval_ptr_dtor(&entry); - return FAILURE; - } - pointer += byte_count; - add_assoc_string(entry, "mail", name, 1); - ares_free_string(name); - - GETLONG(ltmp, pointer); - add_assoc_long(entry, "serial", ltmp); - GETLONG(ltmp, pointer); - add_assoc_long(entry, "refresh", ltmp); - GETLONG(ltmp, pointer); - add_assoc_long(entry, "retry", ltmp); - GETLONG(ltmp, pointer); - add_assoc_long(entry, "expire", ltmp); - GETLONG(ltmp, pointer); - add_assoc_long(entry, "minimum-ttl", ltmp); - break; - - case T_TXT: - for (ltmp = 0; ltmp < byte_count; ltmp += pointer[ltmp] + 1) { - add_next_index_stringl(entry, (const char *) &pointer[ltmp + 1], pointer[ltmp], 1); - } - pointer += byte_count; - break; - - default: - zval_ptr_dtor(&entry); - entry = NULL; - pointer += byte_count; - break; - } - - if (entry) { - add_next_index_zval(result, entry); - } - } - - return SUCCESS; -} -/* }}} */ - -/* {{{ callbacks */ -static void php_ares_callback_func_old(void *aq, int status, unsigned char *abuf, int alen) -{ - php_ares_query *q = (php_ares_query *) aq; - zval *params[4], *retval, *parsed = NULL; - TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls); - - q->error = status; - if (abuf) { - q->result.std.buf = estrndup((char *) abuf, alen); - q->result.std.len = alen; - - MAKE_STD_ZVAL(parsed); - ZVAL_NULL(parsed); - if (SUCCESS == php_ares_parse(abuf, alen, parsed)) { - q->result.std.arr = parsed; - } else { - zval_ptr_dtor(&parsed); - parsed = NULL; - } - } - - if (q->callback) { - MAKE_STD_ZVAL(retval); - MAKE_STD_ZVAL(params[0]); - MAKE_STD_ZVAL(params[1]); - MAKE_STD_ZVAL(params[2]); - ZVAL_NULL(retval); - zend_list_addref(q->id); - Z_LVAL_P(params[0]) = q->id; - Z_TYPE_P(params[0]) = IS_RESOURCE; - ZVAL_LONG(params[1], status); - ZVAL_STRINGL(params[2], (char *) abuf, alen, 1); - - if (parsed) { - ADDREF(parsed); - params[3] = parsed; - } - - q->ares->in_callback = 1; - call_user_function(EG(function_table), NULL, q->callback, retval, parsed ? 4 : 3, params TSRMLS_CC); - q->ares->in_callback = 0; - - zval_ptr_dtor(&retval); - zval_ptr_dtor(¶ms[0]); - zval_ptr_dtor(¶ms[1]); - zval_ptr_dtor(¶ms[2]); - - if (parsed) { - zval_ptr_dtor(¶ms[3]); - } - } -} - -static void php_ares_host_callback_func_old(void *aq, int status, struct hostent *hostent) -{ - php_ares_query *q = (php_ares_query *) aq; - zval *params[3], *retval; - TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls); - - q->error = status; - if (hostent) { - php_ares_hostent_copy(hostent, &q->result.host); - } - - if (q->callback) { - MAKE_STD_ZVAL(retval); - MAKE_STD_ZVAL(params[0]); - MAKE_STD_ZVAL(params[1]); - MAKE_STD_ZVAL(params[2]); - ZVAL_NULL(retval); - zend_list_addref(q->id); - Z_LVAL_P(params[0]) = q->id; - Z_TYPE_P(params[0]) = IS_RESOURCE; - ZVAL_LONG(params[1], status); - object_init(params[2]); - php_ares_hostent_to_struct(hostent, HASH_OF(params[2])); - - q->ares->in_callback = 1; - call_user_function(EG(function_table), NULL, q->callback, retval, 3, params TSRMLS_CC); - q->ares->in_callback = 0; - - zval_ptr_dtor(&retval); - zval_ptr_dtor(¶ms[0]); - zval_ptr_dtor(¶ms[1]); - zval_ptr_dtor(¶ms[2]); - } -} - -#ifdef HAVE_ARES_GETNAMEINFO -static void php_ares_nameinfo_callback_func_old(void *aq, int status, char *node, char *service) -{ - php_ares_query *q = (php_ares_query *) aq; - zval *params[4], *retval; - TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls); - - q->error = status; - if (node) { - q->result.ninfo.node = estrdup(node); - } - if (service) { - q->result.ninfo.service = estrdup(service); - } - - if (q->callback) { - MAKE_STD_ZVAL(retval); - MAKE_STD_ZVAL(params[0]); - MAKE_STD_ZVAL(params[1]); - MAKE_STD_ZVAL(params[2]); - MAKE_STD_ZVAL(params[3]); - ZVAL_NULL(retval); - zend_list_addref(q->id); - Z_LVAL_P(params[0]) = q->id; - Z_TYPE_P(params[0]) = IS_RESOURCE; - ZVAL_LONG(params[1], status); - if (node) { - ZVAL_STRING(params[2], node, 1); - } else { - ZVAL_NULL(params[2]); - } - if (service) { - ZVAL_STRING(params[3], service, 1); - } else { - ZVAL_NULL(params[3]); - } - - q->ares->in_callback = 1; - call_user_function(EG(function_table), NULL, q->callback, retval, 4, params TSRMLS_CC); - q->ares->in_callback = 0; - - zval_ptr_dtor(&retval); - zval_ptr_dtor(¶ms[0]); - zval_ptr_dtor(¶ms[1]); - zval_ptr_dtor(¶ms[2]); - zval_ptr_dtor(¶ms[3]); - } -} -#endif - -#if PHP_ARES_NEW_CALLBACK_API -# define php_ares_callback_func php_ares_callback_func_new -static void php_ares_callback_func_new(void *aq, int status, int timeouts, unsigned char *abuf, int alen) -{ - php_ares_callback_func_old(aq, status, abuf, alen); -} - -# define php_ares_host_callback_func php_ares_host_callback_func_new -static void php_ares_host_callback_func_new(void *aq, int status, int timeouts, struct hostent *hostent) -{ - php_ares_host_callback_func_old(aq, status, hostent); -} - -# ifdef HAVE_ARES_GETNAMEINFO -# define php_ares_nameinfo_callback_func php_ares_nameinfo_callback_func_new -static void php_ares_nameinfo_callback_func_new(void *aq, int status, int timeouts, char *node, char *service) -{ - php_ares_nameinfo_callback_func_old(aq, status, node, service); -} -# endif - -#else -# define php_ares_callback_func php_ares_callback_func_old -# define php_ares_host_callback_func php_ares_host_callback_func_old -# ifdef HAVE_ARES_GETNAMEINFO -# define php_ares_nameinfo_callback_func php_ares_nameinfo_callback_func_old -# endif -#endif -/* }}} */ - -local struct timeval *php_ares_timeout(php_ares *ares, long max_timeout, struct timeval *tv_buf) /* {{{ */ -{ - struct timeval maxtv; - - if (max_timeout > -1) { - maxtv.tv_sec = max_timeout / 1000; - maxtv.tv_usec = max_timeout % (max_timeout * 1000); - } - - return ares_timeout(ares->channel, max_timeout > -1 ? &maxtv : NULL, tv_buf); -} -/* }}} */ - -local int php_ares_process(php_ares *ares, long max_timeout) /* {{{ */ -{ - int nfds; - fd_set R, W; - struct timeval tv; - - FD_ZERO(&R); - FD_ZERO(&W); - - if ((nfds = ares_fds(ares->channel, &R, &W))) { - if (0 < select(nfds, &R, &W, NULL, php_ares_timeout(ares, max_timeout, &tv))) { - ares_process(ares->channel, &R, &W); - } - } - - return nfds; -} -/* }}} */ - -local int php_ares_publish_fds(fd_set *R, fd_set *W, zval *r, zval *w) /* {{{ */ -{ - int i, nfds = 0; - - for (i = 0; i < FD_SETSIZE; ++i) { - if (FD_ISSET(i, R)) { - add_next_index_long(r, i); - if (i > nfds) { - nfds = i; - } - } - } - - for (i = 0; i < FD_SETSIZE; ++i) { - if (FD_ISSET(i, W)) { - add_next_index_long(w, i); - if (i > nfds) { - nfds = i; - } - } - } - - return nfds ? nfds + 1 : 0; -} -/* }}} */ - -local int php_ares_extract_fds(zval *r, zval *w, fd_set *R, fd_set *W) /* {{{ */ -{ - zval **fd; - int nfds = 0; - - 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) { - FD_SET(Z_LVAL_PP(fd), R); - if (Z_LVAL_PP(fd) > nfds) { - nfds = Z_LVAL_PP(fd); - } - } - } - } - - if (w && zend_hash_num_elements(Z_ARRVAL_P(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) { - FD_SET(Z_LVAL_PP(fd), W); - if (Z_LVAL_PP(fd) > nfds) { - nfds = Z_LVAL_PP(fd); - } - } - } - } - - return nfds ? nfds + 1 : 0; -} -/* }}} */ - -static void php_ares_query_llist_dtor(void *entry) -{ - php_ares_query *q = *(php_ares_query **) entry; - TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls); - zend_list_delete(q->id); -} - -#ifdef HAVE_ARES_VERSION -/* {{{ proto string ares_version() - Get libares version */ -static PHP_FUNCTION(ares_version) -{ - if (ZEND_NUM_ARGS()) { - WRONG_PARAM_COUNT; - } - - RETURN_STRING(estrdup(ares_version(NULL)), 0); -} -/* }}} */ -#endif - -/* {{{ proto resource ares_init([array options]) - Create an ares resource */ -static PHP_FUNCTION(ares_init) -{ - zval *opt_array = NULL; - php_ares *ares = NULL; - int err; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &opt_array)) { - RETURN_FALSE; - } - - ares = emalloc(sizeof(php_ares)); - TSRMLS_SET_CTX(ares->tsrm_ls); - zend_llist_init(&ares->queries, sizeof(php_ares_query *), (llist_dtor_func_t) php_ares_query_llist_dtor, 0); - php_ares_options_ctor(&ares->options, opt_array ? Z_ARRVAL_P(opt_array) : NULL); - - if (ARES_SUCCESS != (err = ares_init_options(&ares->channel, &ares->options.strct, ares->options.flags))) { - php_ares_options_dtor(&ares->options); - zend_llist_destroy(&ares->queries); - efree(ares); - RETURN_ARES_ERROR(err); - } - - ZEND_REGISTER_RESOURCE(return_value, ares, le_ares); -} -/* }}} */ - -/* {{{ proto void ares_destroy(resource ares) - Destroy the ares handle */ -static PHP_FUNCTION(ares_destroy) -{ - zval *rsrc; - php_ares *ares; - - if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) { - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - if (ares->in_callback) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot destroy ares handle while in callback"); - } else { - zend_list_delete(Z_LVAL_P(rsrc)); - } - } -} -/* }}} */ - -/* {{{ proto string ares_strerror(int status) - Get description of status code */ -static PHP_FUNCTION(ares_strerror) -{ - long err; -#ifdef HAVE_OLD_ARES_STRERROR - char *__tmp = NULL; - const char *__err; -#endif - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &err)) { - RETURN_FALSE; - } - -#ifdef HAVE_OLD_ARES_STRERROR - __err = ares_strerror(err, &__tmp); - RETVAL_STRING(estrdup(__err), 0); - if (__tmp) { - ares_free_errmem(__tmp); - } -#else - RETURN_STRING(estrdup(ares_strerror(err)), 0); -#endif -} -/* }}} */ - -/* {{{ proto string ares_mkquery(string name, int dnsclass, int type, int id, int rd) - Compose a custom query */ -static PHP_FUNCTION(ares_mkquery) -{ - char *name_str, *query_str; - int name_len, query_len, err; - long dnsclass, type, id, rd; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sllll", &name_str, &name_len, &dnsclass, &type, &id, &rd)) { - RETURN_FALSE; - } - - if (ARES_SUCCESS != (err = ares_mkquery(name_str, dnsclass, type, id, rd, (unsigned char **) &query_str, &query_len))) { - RETURN_ARES_ERROR(err); - } - RETVAL_STRINGL(query_str, query_len, 1); - ares_free_string(query_str); -} -/* }}} */ - -/* {{{ proto resource ares_search(resource ares, mixed callback, string name[, int type = ARES_T_A[, int dnsclass = ARES_C_IN]]) - Issue a domain search for name */ -static PHP_FUNCTION(ares_search) -{ - zval *rsrc, *cb = NULL; - php_ares *ares; - php_ares_query *query; - char *name; - int name_len; - long dnsclass = C_IN, type = T_A; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|ll", &rsrc, &cb, &name, &name_len, &type, &dnsclass)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - - if (cb && !IS_CALLABLE(cb, 0, NULL)) { - RETURN_ARES_CB_ERROR("second"); - } - - query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb); - php_ares_query_rsrc(query, return_value); - php_ares_query_pckt(query, PHP_ARES_PCKT_SEARCH, name, name_len, type, dnsclass); - ares_search(ares->channel, name, dnsclass, type, php_ares_callback_func, query); -} -/* }}} */ - -/* {{{ proto resource ares_query(resource ares, mixed callback, string name[, int type = ARES_T_A[, int dnsclass = ARES_C_IN]]) - Issue a single DNS query */ -static PHP_FUNCTION(ares_query) -{ - zval *rsrc, *cb = NULL; - php_ares *ares; - php_ares_query *query; - char *name; - int name_len; - long dnsclass = C_IN, type = T_A; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|ll", &rsrc, &cb, &name, &name_len, &type, &dnsclass)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - - if (cb && !IS_CALLABLE(cb, 0, NULL)) { - RETURN_ARES_CB_ERROR("second"); - } - - query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb); - php_ares_query_rsrc(query, return_value); - php_ares_query_pckt(query, PHP_ARES_PCKT_QUERY, name, name_len, type, dnsclass); - ares_query(ares->channel, name, dnsclass, type, php_ares_callback_func, query); -} -/* }}} */ - -/* {{{ proto resource ares_send(resource ares, mixed callback, string buf) - Send custom query */ -static PHP_FUNCTION(ares_send) -{ - zval *rsrc, *cb = NULL; - php_ares *ares; - php_ares_query *query; - char *buf; - int len; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s", &rsrc, &cb, &buf, &len)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - - if (cb && !IS_CALLABLE(cb, 0, NULL)) { - RETURN_ARES_CB_ERROR("second"); - } - - query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb); - php_ares_query_rsrc(query, return_value); - php_ares_query_pckt(query, PHP_ARES_PCKT_SEND, buf, len); - ares_send(ares->channel, (const unsigned char *) buf, len, php_ares_callback_func, query); -} -/* }}} */ - -/* {{{ proto resource ares_gethostbyname(resource ares, mixed callback, string name[, int family = AF_INET]) - Get host by name */ -static PHP_FUNCTION(ares_gethostbyname) -{ - zval *rsrc, *cb = NULL; - php_ares *ares; - php_ares_query *query; - char *name; - int name_len; - long family = AF_INET; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|l", &rsrc, &cb, &name, &name_len, &family)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - - if (cb && !IS_CALLABLE(cb, 0, NULL)) { - RETURN_ARES_CB_ERROR("second"); - } - - query = php_ares_query_ctor(NULL, PHP_ARES_CB_HOST, ares, cb); - php_ares_query_rsrc(query, return_value); - php_ares_query_pckt(query, PHP_ARES_PCKT_HNAME, name, name_len, family); - ares_gethostbyname(ares->channel, name, family, php_ares_host_callback_func, query); -} -/* }}} */ - -/* {{{ proto resource ares_gethostbyaddr(resuorce ares, mixed callback, string address[, int family = ARES_AF_INET]) - Get host by address */ -static PHP_FUNCTION(ares_gethostbyaddr) -{ - zval *rsrc, *cb = NULL; - php_ares *ares; - php_ares_query *query; - char *addr; - int addr_len; - long family = AF_INET; - void *sa; - int sa_len; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|l", &rsrc, &cb, &addr, &addr_len, &family)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - - if (cb && !IS_CALLABLE(cb, 0, NULL)) { - PHP_ARES_CB_ERROR("second"); - RETURN_FALSE; - } - - switch (family) { - case AF_INET: - sa = emalloc(sa_len = sizeof(struct in_addr)); - break; - case AF_INET6: - sa = emalloc(sa_len = sizeof(struct in6_addr)); - break; - default: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter family is neither ARES_AF_INET nor ARES_AF_INET6"); - RETURN_FALSE; - break; - } - - if (1 > inet_pton(family, addr, sa)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr); - RETVAL_FALSE; - } else { - query = php_ares_query_ctor(NULL, PHP_ARES_CB_HOST, ares, cb); - php_ares_query_rsrc(query, return_value); - php_ares_query_pckt(query, PHP_ARES_PCKT_HADDR, addr, addr_len, family); - ares_gethostbyaddr(ares->channel, sa, sa_len, family, php_ares_host_callback_func, query); - } - efree(sa); -} -/* }}} */ - -#ifdef HAVE_ARES_GETNAMEINFO -/* {{{ proto resource ares_getnameinfo(resource ares, mixed callback, int flags, string addr[, int family = ARES_AF_INET[, int port = 0]]) - Get name info */ -static PHP_FUNCTION(ares_getnameinfo) -{ - zval *rsrc, *cb = NULL; - php_ares *ares; - php_ares_query *query; - char *addr; - int addr_len; - long flags, port = 0, family = AF_INET; - struct sockaddr *sa; - struct sockaddr_in *in; - struct sockaddr_in6 *in6; - int sa_len; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!ls|ll", &rsrc, &cb, &flags, &addr, &addr_len, &family, &port)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - - if (cb && !IS_CALLABLE(cb, 0, NULL)) { - PHP_ARES_CB_ERROR("second"); - RETURN_FALSE; - } - - RETVAL_TRUE; - switch (family) { - case AF_INET: - in = ecalloc(1, sa_len = sizeof(struct sockaddr_in)); - in->sin_family = AF_INET; - in->sin_port = htons((unsigned short) port); - if (1 > inet_pton(in->sin_family, addr, &in->sin_addr)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr); - RETVAL_FALSE; - } - sa = (struct sockaddr *) in; - break; - case AF_INET6: - in6 = ecalloc(1, sa_len = sizeof(struct sockaddr_in6)); - in6->sin6_family = AF_INET6; - in6->sin6_port = htons((unsigned short) port); - if (1 > inet_pton(in6->sin6_family, addr, &in6->sin6_addr)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr); - RETVAL_FALSE; - } - sa = (struct sockaddr *) in6; - break; - default: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter family is neither AF_INET nor AF_INET6"); - RETURN_FALSE; - break; - } - - if (Z_BVAL_P(return_value)) { - query = php_ares_query_ctor(NULL, PHP_ARES_CB_NINFO, ares, cb); - php_ares_query_rsrc(query, return_value); - php_ares_query_pckt(query, PHP_ARES_PCKT_NINFO, flags, addr, addr_len, family, port); - ares_getnameinfo(ares->channel, sa, sa_len, flags, php_ares_nameinfo_callback_func, query); - } - efree(sa); -} -/* }}} */ -#endif - -/* {{{ proto mixed ares_result(resource query, int &errno, string &error) - Check a query for its result */ -static PHP_FUNCTION(ares_result) -{ - zval *rsrc, *zerrno = NULL, *zerror = NULL; - php_ares_query *query; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|zz", &rsrc, &zerrno, &zerror)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(query, php_ares_query *, &rsrc, -1, PHP_ARES_QUERY_LE_NAME, le_ares_query); - - if (zerrno) { - zval_dtor(zerrno); - ZVAL_LONG(zerrno, query->error); - } - if (zerror) { - zval_dtor(zerror); - ZVAL_NULL(zerror); - } - - switch (query->error) { - case 0: - switch (query->type) { - case PHP_ARES_CB_STD: - if (query->result.std.arr) { - RETVAL_ZVAL(query->result.std.arr, 1, 0); - } else { - RETVAL_STRINGL(query->result.std.buf, query->result.std.len, 1); - } - break; - case PHP_ARES_CB_HOST: - object_init(return_value); - php_ares_hostent_to_struct(&query->result.host, HASH_OF(return_value)); - break; - case PHP_ARES_CB_NINFO: - object_init(return_value); - add_property_string(return_value, "node", query->result.ninfo.node ? query->result.ninfo.node : "", 1); - add_property_string(return_value, "service", query->result.ninfo.service ? query->result.ninfo.service : "", 1); - break; - } - break; - case -1: - RETVAL_FALSE; - break; - default: - if (zerror) { -#ifdef HAVE_OLD_ARES_STRERROR - char *__tmp = NULL; - const char *__err = ares_strerror(query->error, &__tmp); - ZVAL_STRING(zerror, estrdup(__err), 0); - if (__tmp) ares_free_errmem(__tmp); -#else - ZVAL_STRING(zerror, estrdup(ares_strerror(query->error)), 0); -#endif - } - RETVAL_FALSE; - break; - } -} -/* }}} */ - -/* {{{ proto object ares_packet(resource query) - Check a query for its question packet */ -static PHP_FUNCTION(ares_packet) -{ - zval *rsrc, *prop; - php_ares_query *query; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(query, php_ares_query *, &rsrc, -1, PHP_ARES_QUERY_LE_NAME, le_ares_query); - - object_init(return_value); - add_property_long(return_value, "type", query->packet.type); - add_property_null(return_value, "search"); - add_property_null(return_value, "query"); - add_property_null(return_value, "send"); - add_property_null(return_value, "gethostbyname"); - add_property_null(return_value, "gethostbyaddr"); - add_property_null(return_value, "getnameinfo"); - MAKE_STD_ZVAL(prop); - - switch (query->packet.type) { - case PHP_ARES_PCKT_SEARCH: - object_init(prop); - add_property_stringl(prop, "name", query->packet.data.search.name, query->packet.data.search.name_len, 1); - add_property_long(prop, "type", query->packet.data.search.type); - add_property_long(prop, "dnsclass", query->packet.data.search.dnsclass); - add_property_zval(return_value, "search", prop); - break; - - case PHP_ARES_PCKT_QUERY: - object_init(prop); - add_property_stringl(prop, "name", query->packet.data.query.name, query->packet.data.query.name_len, 1); - add_property_long(prop, "type", query->packet.data.query.type); - add_property_long(prop, "dnsclass", query->packet.data.query.dnsclass); - add_property_zval(return_value, "query", prop); - break; - - case PHP_ARES_PCKT_SEND: - ZVAL_STRINGL(prop, query->packet.data.send.buf, query->packet.data.send.len, 1); - add_property_zval(return_value, "send", prop); - break; - - case PHP_ARES_PCKT_HNAME: - object_init(prop); - add_property_stringl(prop, "name", query->packet.data.hname.name, query->packet.data.hname.name_len, 1); - add_property_long(prop, "family", query->packet.data.hname.family); - add_property_zval(return_value, "gethostbyname", prop); - break; - - case PHP_ARES_PCKT_HADDR: - object_init(prop); - add_property_stringl(prop, "addr", query->packet.data.haddr.addr, query->packet.data.haddr.addr_len, 1); - add_property_long(prop, "family", query->packet.data.haddr.family); - add_property_zval(return_value, "gethostbyaddr", prop); - break; - - case PHP_ARES_PCKT_NINFO: - object_init(prop); - add_property_long(prop, "flags", query->packet.data.ninfo.flags); - add_property_stringl(prop, "addr", query->packet.data.ninfo.addr, query->packet.data.ninfo.addr_len, 1); - add_property_long(prop, "family", query->packet.data.ninfo.family); - add_property_long(prop, "port", query->packet.data.ninfo.port); - add_property_zval(return_value, "getnameinfo", prop); - break; - } - - zval_ptr_dtor(&prop); -} -/* }}} */ - -#ifdef HAVE_ARES_CANCEL -/* {{{ proto void ares_cancel(resource ares) - Cancel pending queries */ -static PHP_FUNCTION(ares_cancel) -{ - zval *rsrc; - php_ares *ares; - - if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) { - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - ares_cancel(ares->channel); - } -} -/* }}} */ -#endif - -/* {{{ proto void ares_process_all(resource ares[, int max_timeout_ms]) - Process all pending queries */ -static PHP_FUNCTION(ares_process_all) -{ - zval *rsrc; - php_ares *ares; - long max_timeout = -1; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - - while (php_ares_process(ares, max_timeout)); -} -/* }}} */ - -/* {{{ proto bool ares_process_once(resource ares[, int max_timout_ms]) - Process once and return whether it should be called again */ -static PHP_FUNCTION(ares_process_once) -{ - zval *rsrc; - php_ares *ares; - long max_timeout = -1; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - - RETVAL_BOOL(php_ares_process(ares, max_timeout)); -} -/* }}} */ - -/* {{{ proto void ares_process(resource ares, array read, array write) - Process call */ -static PHP_FUNCTION(ares_process) -{ - zval *rsrc, *read = NULL, *write = NULL; - fd_set R, W; - php_ares *ares; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|a!a!", &rsrc, &read, &write)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - - FD_ZERO(&R); - FD_ZERO(&W); - - php_ares_extract_fds(read, write, &R, &W); - ares_process(ares->channel, &R, &W); -} -/* }}} */ - -/* proto bool ares_select(array &read, array &write, int timeout_ms) - Select call */ -static PHP_FUNCTION(ares_select) -{ - zval *read = NULL, *write = NULL; - fd_set R, W; - int nfds; - long timeout; - struct timeval tv; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aal", &read, &write, &timeout)) { - RETURN_FALSE; - } - - if (timeout) { - tv.tv_sec = timeout / 1000; - tv.tv_usec = timeout % (timeout * 1000); - } else { - tv.tv_sec = 1; - tv.tv_usec = 0; - } - - FD_ZERO(&R); - FD_ZERO(&W); - - nfds = php_ares_extract_fds(read, write, &R, &W); - 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; - } - RETURN_FALSE; -} -/* }}} */ - -/* proto int ares_timeout(resource ares[, int max_timout_ms]) - Get suggested select timeout in ms */ -static PHP_FUNCTION(ares_timeout) -{ - zval *rsrc; - long max_timeout = -1; - struct timeval tv, *tvptr; - php_ares *ares; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - - if ((tvptr = php_ares_timeout(ares, max_timeout, &tv))) { - RETURN_LONG(tvptr->tv_sec * 1000 + tvptr->tv_usec / 1000); - } - RETURN_LONG(0); -} -/* }}} */ - -/* {{{ proto int ares_fds(resource ares, array &read, array &write) - Get file descriptors */ -static PHP_FUNCTION(ares_fds) -{ - zval *rsrc, *read, *write; - fd_set R, W; - php_ares *ares; - - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzz", &rsrc, &read, &write)) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); - - FD_ZERO(&R); - FD_ZERO(&W); - - zval_dtor(read); - zval_dtor(write); - array_init(read); - array_init(write); - ares_fds(ares->channel, &R, &W); - RETVAL_LONG(php_ares_publish_fds(&R, &W, read, write)); -} -/* }}} */ - -static ZEND_RSRC_DTOR_FUNC(php_ares_le_dtor) -{ - php_ares *ares = (php_ares *) rsrc->ptr; - - ares_destroy(ares->channel); - zend_llist_destroy(&ares->queries); - php_ares_options_dtor(&ares->options); - efree(ares); -} - -static ZEND_RSRC_DTOR_FUNC(php_ares_query_le_dtor) -{ - php_ares_query *query = (php_ares_query *) rsrc->ptr; - - php_ares_query_dtor(query); - efree(query); -} - -/* {{{ PHP_MINIT_FUNCTION */ -static PHP_MINIT_FUNCTION(ares) -{ -#ifdef HAVE_ARES_LIBRARY_INIT - if (ARES_SUCCESS != ares_library_init(ARES_LIB_INIT_ALL)) { - return FAILURE; - } -#endif -#ifdef HAVE_ARES_VERSION - { - int ares_version_num; - ares_version(&ares_version_num); - - REGISTER_LONG_CONSTANT("ARES_VERSION", ares_version_num, CONST_PERSISTENT|CONST_CS); - } -#endif - - REGISTER_LONG_CONSTANT("ARES_SUCCESS", ARES_SUCCESS, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_ENODATA", ARES_ENODATA, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_EFORMERR", ARES_EFORMERR, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_ESERVFAIL", ARES_ESERVFAIL, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_ENOTFOUND", ARES_ENOTFOUND, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_ENOTIMP", ARES_ENOTIMP, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_EREFUSED", ARES_EREFUSED, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_EBADQUERY", ARES_EBADQUERY, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_EBADNAME", ARES_EBADNAME, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_EBADFAMILY", ARES_EBADFAMILY, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_EBADRESP", ARES_EBADRESP, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_ECONNREFUSED", ARES_ECONNREFUSED, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_ETIMEOUT", ARES_ETIMEOUT, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_EOF", ARES_EOF, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_EFILE", ARES_EFILE, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_ENOMEM", ARES_ENOMEM, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_EDESTRUCTION", ARES_EDESTRUCTION, CONST_PERSISTENT|CONST_CS); -#ifdef ARES_EBADSTR - REGISTER_LONG_CONSTANT("ARES_EBADSTR", ARES_EBADSTR, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_EBADFLAGS - REGISTER_LONG_CONSTANT("ARES_EBADFLAGS", ARES_EBADFLAGS, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_ENONAME - REGISTER_LONG_CONSTANT("ARES_ENONAME", ARES_ENONAME, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_EBADHINTS - REGISTER_LONG_CONSTANT("ARES_EBADHINTS", ARES_EBADHINTS, CONST_PERSISTENT|CONST_CS); -#endif - - REGISTER_LONG_CONSTANT("ARES_FLAG_USEVC", ARES_FLAG_USEVC, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_FLAG_PRIMARY", ARES_FLAG_PRIMARY, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_FLAG_IGNTC", ARES_FLAG_IGNTC, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_FLAG_NORECURSE", ARES_FLAG_NORECURSE, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_FLAG_STAYOPEN", ARES_FLAG_STAYOPEN, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_FLAG_NOSEARCH", ARES_FLAG_NOSEARCH, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_FLAG_NOALIASES", ARES_FLAG_NOALIASES, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_FLAG_NOCHECKRESP", ARES_FLAG_NOCHECKRESP, CONST_PERSISTENT|CONST_CS); - - /* - * Address Family Constants - */ - REGISTER_LONG_CONSTANT("ARES_AF_INET", AF_INET, CONST_PERSISTENT|CONST_CS); - REGISTER_LONG_CONSTANT("ARES_AF_INET6", AF_INET6, CONST_PERSISTENT|CONST_CS); - - /* - * Name Info constants - */ -#ifdef ARES_NI_NOFQDN - REGISTER_LONG_CONSTANT("ARES_NI_NOFQDN", ARES_NI_NOFQDN, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_NUMERICHOST - REGISTER_LONG_CONSTANT("ARES_NI_NUMERICHOST", ARES_NI_NUMERICHOST, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_NAMEREQD - REGISTER_LONG_CONSTANT("ARES_NI_NAMEREQD", ARES_NI_NAMEREQD, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_NUMERICSERV - REGISTER_LONG_CONSTANT("ARES_NI_NUMERICSERV", ARES_NI_NUMERICSERV, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_DGRAM - REGISTER_LONG_CONSTANT("ARES_NI_DGRAM", ARES_NI_DGRAM, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_TCP - REGISTER_LONG_CONSTANT("ARES_NI_TCP", ARES_NI_TCP, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_UDP - REGISTER_LONG_CONSTANT("ARES_NI_UDP", ARES_NI_UDP, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_SCTP - REGISTER_LONG_CONSTANT("ARES_NI_SCTP", ARES_NI_SCTP, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_DCCP - REGISTER_LONG_CONSTANT("ARES_NI_DCCP", ARES_NI_DCCP, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_NUMERICSCOPE - REGISTER_LONG_CONSTANT("ARES_NI_NUMERICSCOPE", ARES_NI_NUMERICSCOPE, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_LOOKUPHOST - REGISTER_LONG_CONSTANT("ARES_NI_LOOKUPHOST", ARES_NI_LOOKUPHOST, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_LOOKUPSERVICE - REGISTER_LONG_CONSTANT("ARES_NI_LOOKUPSERVICE", ARES_NI_LOOKUPSERVICE, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_IDN - REGISTER_LONG_CONSTANT("ARES_NI_IDN", ARES_NI_IDN, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_IDN_ALLOW_UNASSIGNED - REGISTER_LONG_CONSTANT("ARES_NI_IDN_ALLOW_UNASSIGNED", ARES_NI_IDN_ALLOW_UNASSIGNED, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_NI_IDN_USE_STD - REGISTER_LONG_CONSTANT("ARES_NI_IDN_USE_STD", ARES_NI_IDN_USE_STD, CONST_PERSISTENT|CONST_CS); -#endif - - /* - * Address Info constants - */ -#ifdef ARES_AI_CANONNAME - REGISTER_LONG_CONSTANT("ARES_AI_CANONNAME", ARES_AI_CANONNAME, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_AI_NUMERICHOST - REGISTER_LONG_CONSTANT("ARES_AI_NUMERICHOST", ARES_AI_NUMERICHOST, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_AI_PASSIVE - REGISTER_LONG_CONSTANT("ARES_AI_PASSIVE", ARES_AI_PASSIVE, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_AI_NUMERICSERV - REGISTER_LONG_CONSTANT("ARES_AI_NUMERICSERV", ARES_AI_NUMERICSERV, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_AI_V - REGISTER_LONG_CONSTANT("ARES_AI_V", ARES_AI_V, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_AI_ALL - REGISTER_LONG_CONSTANT("ARES_AI_ALL", ARES_AI_ALL, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_AI_ADDRCONFIG - REGISTER_LONG_CONSTANT("ARES_AI_ADDRCONFIG", ARES_AI_ADDRCONFIG, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_AI_IDN - REGISTER_LONG_CONSTANT("ARES_AI_IDN", ARES_AI_IDN, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_AI_IDN_ALLOW_UNASSIGNED - REGISTER_LONG_CONSTANT("ARES_AI_IDN_ALLOW_UNASSIGNED", ARES_AI_IDN_ALLOW_UNASSIGNED, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_AI_IDN_USE_STD - REGISTER_LONG_CONSTANT("ARES_AI_IDN_USE_STD", ARES_AI_IDN_USE_STD, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_AI_CANONIDN - REGISTER_LONG_CONSTANT("ARES_AI_CANONIDN", ARES_AI_CANONIDN, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_AI_MASK - REGISTER_LONG_CONSTANT("ARES_AI_MASK", ARES_AI_MASK, CONST_PERSISTENT|CONST_CS); -#endif -#ifdef ARES_GETSOCK_MAXNUM - REGISTER_LONG_CONSTANT("ARES_GETSOCK_MAXNUM", ARES_GETSOCK_MAXNUM, CONST_PERSISTENT|CONST_CS); -#endif - - /* - * ns_t (type) constants (arpa/nameser.h) - */ - - /* (1) Host address. */ - REGISTER_LONG_CONSTANT("ARES_T_A", T_A, CONST_CS|CONST_PERSISTENT); - /* (2) Authoritative server. */ - REGISTER_LONG_CONSTANT("ARES_T_NS", T_NS, CONST_CS|CONST_PERSISTENT); - /* (3) Mail destination. */ - REGISTER_LONG_CONSTANT("ARES_T_MD", T_MD, CONST_CS|CONST_PERSISTENT); - /* (4) Mail forwarder. */ - REGISTER_LONG_CONSTANT("ARES_T_MF", T_MF, CONST_CS|CONST_PERSISTENT); - /* (5) Canonical name. */ - REGISTER_LONG_CONSTANT("ARES_T_CNAME", T_CNAME, CONST_CS|CONST_PERSISTENT); - /* (6) Start of authority zone. */ - REGISTER_LONG_CONSTANT("ARES_T_SOA", T_SOA, CONST_CS|CONST_PERSISTENT); - /* (7) Mailbox domain name. */ - REGISTER_LONG_CONSTANT("ARES_T_MB", T_MB, CONST_CS|CONST_PERSISTENT); - /* (8) Mail group member. */ - REGISTER_LONG_CONSTANT("ARES_T_MG", T_MG, CONST_CS|CONST_PERSISTENT); - /* (9) Mail rename name. */ - REGISTER_LONG_CONSTANT("ARES_T_MR", T_MR, CONST_CS|CONST_PERSISTENT); - /* (10) Null resource record. */ - REGISTER_LONG_CONSTANT("ARES_T_NULL", T_NULL, CONST_CS|CONST_PERSISTENT); - /* (11) Well known service. */ - REGISTER_LONG_CONSTANT("ARES_T_WKS", T_WKS, CONST_CS|CONST_PERSISTENT); - /* (12) Domain name pointer. */ - REGISTER_LONG_CONSTANT("ARES_T_PTR", T_PTR, CONST_CS|CONST_PERSISTENT); - /* (13) Host information. */ - REGISTER_LONG_CONSTANT("ARES_T_HINFO", T_HINFO, CONST_CS|CONST_PERSISTENT); - /* (14) Mailbox information. */ - REGISTER_LONG_CONSTANT("ARES_T_MINFO", T_MINFO, CONST_CS|CONST_PERSISTENT); - /* (15) Mail routing information. */ - REGISTER_LONG_CONSTANT("ARES_T_MX", T_MX, CONST_CS|CONST_PERSISTENT); - /* (16) Text strings. */ - REGISTER_LONG_CONSTANT("ARES_T_TXT", T_TXT, CONST_CS|CONST_PERSISTENT); - /* (17) Responsible person. */ - REGISTER_LONG_CONSTANT("ARES_T_RP", T_RP, CONST_CS|CONST_PERSISTENT); - /* (18) AFS cell database. */ - REGISTER_LONG_CONSTANT("ARES_T_AFSDB", T_AFSDB, CONST_CS|CONST_PERSISTENT); - /* (19) X_25 calling address. */ - REGISTER_LONG_CONSTANT("ARES_T_X25", T_X25, CONST_CS|CONST_PERSISTENT); - /* (20) ISDN calling address. */ - REGISTER_LONG_CONSTANT("ARES_T_ISDN", T_ISDN, CONST_CS|CONST_PERSISTENT); - /* (21) Router. */ - REGISTER_LONG_CONSTANT("ARES_T_RT", T_RT, CONST_CS|CONST_PERSISTENT); - /* (22) NSAP address. */ - REGISTER_LONG_CONSTANT("ARES_T_NSAP", T_NSAP, CONST_CS|CONST_PERSISTENT); - /* (23) Reverse NSAP lookup (deprecated). */ - /* REGISTER_LONG_CONSTANT("ARES_T_NSAP_PTR", T_NSAP_PTR, CONST_CS|CONST_PERSISTENT); */ - /* (24) Security signature. */ - REGISTER_LONG_CONSTANT("ARES_T_SIG", T_SIG, CONST_CS|CONST_PERSISTENT); - /* (25) Security key. */ - REGISTER_LONG_CONSTANT("ARES_T_KEY", T_KEY, CONST_CS|CONST_PERSISTENT); - /* (26) X.400 mail mapping. */ - REGISTER_LONG_CONSTANT("ARES_T_PX", T_PX, CONST_CS|CONST_PERSISTENT); - /* (27) Geographical position (withdrawn). */ - /* REGISTER_LONG_CONSTANT("ARES_T_GPOS", T_GPOS, CONST_CS|CONST_PERSISTENT); */ - /* (28) Ip6 Address. */ - REGISTER_LONG_CONSTANT("ARES_T_AAAA", T_AAAA, CONST_CS|CONST_PERSISTENT); - /* (29) Location Information. */ - REGISTER_LONG_CONSTANT("ARES_T_LOC", T_LOC, CONST_CS|CONST_PERSISTENT); - /* (30) Next domain (security). */ - REGISTER_LONG_CONSTANT("ARES_T_NXT", T_NXT, CONST_CS|CONST_PERSISTENT); - /* (31) Endpoint identifier. */ - REGISTER_LONG_CONSTANT("ARES_T_EID", T_EID, CONST_CS|CONST_PERSISTENT); - /* (32) Nimrod Locator. */ - REGISTER_LONG_CONSTANT("ARES_T_NIMLOC", T_NIMLOC, CONST_CS|CONST_PERSISTENT); - /* (33) Server Selection. */ - REGISTER_LONG_CONSTANT("ARES_T_SRV", T_SRV, CONST_CS|CONST_PERSISTENT); - /* (34) ATM Address */ - REGISTER_LONG_CONSTANT("ARES_T_ATMA", T_ATMA, CONST_CS|CONST_PERSISTENT); - /* (35) Naming Authority PoinTeR */ - REGISTER_LONG_CONSTANT("ARES_T_NAPTR", T_NAPTR, CONST_CS|CONST_PERSISTENT); - /* (36) Key Exchange */ - /* REGISTER_LONG_CONSTANT("ARES_T_KX", T_KX, CONST_CS|CONST_PERSISTENT); */ - /* (37) Certification record */ - /* REGISTER_LONG_CONSTANT("ARES_T_CERT", T_CERT, CONST_CS|CONST_PERSISTENT); */ - /* (38) IPv6 address (deprecates AAAA) */ - REGISTER_LONG_CONSTANT("ARES_T_A6", T_A6, CONST_CS|CONST_PERSISTENT); - /* (39) Non-terminal DNAME (for IPv6) */ - REGISTER_LONG_CONSTANT("ARES_T_DNAME", T_DNAME, CONST_CS|CONST_PERSISTENT); - /* (40) Kitchen sink (experimentatl) */ - /* REGISTER_LONG_CONSTANT("ARES_T_SINK", T_SINK, CONST_CS|CONST_PERSISTENT); */ - /* (41) EDNS0 option (meta-RR) */ - /* REGISTER_LONG_CONSTANT("ARES_T_OPT", T_OPT, CONST_CS|CONST_PERSISTENT); */ - /* (250) Transaction signature. */ - REGISTER_LONG_CONSTANT("ARES_T_TSIG", T_TSIG, CONST_CS|CONST_PERSISTENT); - /* (251) Incremental zone transfer. */ - REGISTER_LONG_CONSTANT("ARES_T_IXFR", T_IXFR, CONST_CS|CONST_PERSISTENT); - /* (252) Transfer zone of authority. */ - REGISTER_LONG_CONSTANT("ARES_T_AXFR", T_AXFR, CONST_CS|CONST_PERSISTENT); - /* (253) Transfer mailbox records. */ - REGISTER_LONG_CONSTANT("ARES_T_MAILB", T_MAILB, CONST_CS|CONST_PERSISTENT); - /* (254) Transfer mail agent records. */ - REGISTER_LONG_CONSTANT("ARES_T_MAILA", T_MAILA, CONST_CS|CONST_PERSISTENT); - /* (255) Wildcard match. */ - REGISTER_LONG_CONSTANT("ARES_T_ANY", T_ANY, CONST_CS|CONST_PERSISTENT); - - /* - * ns_c (dnsclass) constants (arpa/nameser.h) - */ - - /* (1) Internet. */ - REGISTER_LONG_CONSTANT("ARES_C_IN", C_IN, CONST_CS|CONST_PERSISTENT); - /* (2) unallocated/unsupported. */ - /* REGISTER_LONG_CONSTANT("ARES_C_2", C_2, CONST_CS|CONST_PERSISTENT); */ - /* (3) MIT Chaos-net. */ - REGISTER_LONG_CONSTANT("ARES_C_CHAOS", C_CHAOS, CONST_CS|CONST_PERSISTENT); - /* (4) MIT Hesiod. */ - REGISTER_LONG_CONSTANT("ARES_C_HS", C_HS, CONST_CS|CONST_PERSISTENT); - /* (254) for prereq. sections in update requests */ - /* REGISTER_LONG_CONSTANT("ARES_C_NONE", C_NONE, CONST_CS|CONST_PERSISTENT); */ - /* (255) Wildcard match. */ - REGISTER_LONG_CONSTANT("ARES_C_ANY", C_ANY, CONST_CS|CONST_PERSISTENT); - - le_ares = zend_register_list_destructors_ex(php_ares_le_dtor, NULL, PHP_ARES_LE_NAME, module_number); - le_ares_query = zend_register_list_destructors_ex(php_ares_query_le_dtor, NULL, PHP_ARES_QUERY_LE_NAME, module_number); - - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MSHUTDOWN_FUNCTION */ -static PHP_MSHUTDOWN_FUNCTION(ares) -{ -#ifdef HAVE_ARES_LIBRARY_CLEANUP - ares_library_cleanup(); -#endif - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION */ -static PHP_MINFO_FUNCTION(ares) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "AsyncResolver support", "enabled"); - php_info_print_table_row(2, "Version", PHP_ARES_VERSION); - php_info_print_table_end(); - - php_info_print_table_start(); - php_info_print_table_header(3, "Used Library", "compiled", "linked"); - php_info_print_table_row(3, - PHP_ARES_LIBNAME, -#ifdef ARES_VERSION_STR - ARES_VERSION_STR, -#else - "unkown", -#endif -#ifdef HAVE_ARES_VERSION - ares_version(NULL) -#else - "unkown" -#endif - ); - php_info_print_table_end(); -} -/* }}} */ - -#ifdef ZEND_ENGINE_2 -ZEND_BEGIN_ARG_INFO(ai_ares_select, 0) - ZEND_ARG_PASS_INFO(1) - ZEND_ARG_PASS_INFO(1) - ZEND_ARG_PASS_INFO(0) -ZEND_END_ARG_INFO(); - -ZEND_BEGIN_ARG_INFO(ai_ares_result, 0) - ZEND_ARG_PASS_INFO(0) - ZEND_ARG_PASS_INFO(1) - ZEND_ARG_PASS_INFO(1) -ZEND_END_ARG_INFO(); - -ZEND_BEGIN_ARG_INFO(ai_ares_fds, 0) - ZEND_ARG_PASS_INFO(0) - ZEND_ARG_PASS_INFO(1) - ZEND_ARG_PASS_INFO(1) -ZEND_END_ARG_INFO(); -#else -static unsigned char ai_ares_select[] = {3, BYREF_FORCE, BYREF_FORCE, BYREF_NONE}; -static unsigned char ai_ares_result[] = {4, BYREF_NONE, BYREF_FORCE, BYREF_FORCE}; -static unsigned char ai_ares_fds[] = {4, BYREF_NONE, BYREF_FORCE, BYREF_FORCE}; -#endif - -/* {{{ ares_functions[] */ -zend_function_entry ares_functions[] = { -#ifdef HAVE_ARES_VERSION - PHP_FE(ares_version, NULL) -#endif - PHP_FE(ares_init, NULL) - PHP_FE(ares_destroy, NULL) - PHP_FE(ares_strerror, NULL) -#ifdef HAVE_ARES_CANCEL - PHP_FE(ares_cancel, NULL) -#endif - PHP_FE(ares_search, NULL) - PHP_FE(ares_query, NULL) - PHP_FE(ares_send, NULL) - PHP_FE(ares_mkquery, NULL) - PHP_FE(ares_gethostbyname, NULL) - PHP_FE(ares_gethostbyaddr, NULL) -#ifdef HAVE_ARES_GETNAMEINFO - PHP_FE(ares_getnameinfo, NULL) -#endif - PHP_FE(ares_result, ai_ares_result) - PHP_FE(ares_packet, NULL) - PHP_FE(ares_process_all, NULL) - PHP_FE(ares_process_once, NULL) - PHP_FE(ares_process, NULL) - PHP_FE(ares_select, ai_ares_select) - PHP_FE(ares_fds, ai_ares_fds) - PHP_FE(ares_timeout, NULL) - {NULL, NULL, NULL} -}; -/* }}} */ - -/* {{{ ares_module_entry */ -zend_module_entry ares_module_entry = { - STANDARD_MODULE_HEADER, - "ares", - ares_functions, - PHP_MINIT(ares), - PHP_MSHUTDOWN(ares), - NULL, - NULL, - PHP_MINFO(ares), - PHP_ARES_VERSION, - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -#ifdef COMPILE_DL_ARES -ZEND_GET_MODULE(ares) -#endif - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/config.m4 b/config.m4 index f90065f..06af477 100644 --- a/config.m4 +++ b/config.m4 @@ -1,7 +1,7 @@ dnl $Id$ dnl config.m4 for extension ares -PHP_ARG_WITH(ares, for asynchronous resolver support, +PHP_ARG_WITH(ares, [enable asynchronous resolver support], [ --with-ares Include asynchronous resolver support]) if test "$PHP_ARES" != "no"; then @@ -18,30 +18,46 @@ if test "$PHP_ARES" != "no"; then AC_MSG_ERROR(could not find ares.h) fi - dnl ########## - dnl newer versions of libcares need -lrt - dnl ########## - PHP_ADD_LIBRARY(rt, 1, ARES_SHARED_LIBADD) - PHP_ARES_LIB= + PHP_ARES_LIBADD= PHP_CHECK_LIBRARY(cares, ares_init, [ PHP_ARES_LIB=cares ], [ PHP_CHECK_LIBRARY(ares, ares_init, [ PHP_ARES_LIB=ares ], [ - PHP_ARES_LIB=unknown + PHP_CHECK_LIBRARY(cares, ares_init, [ + PHP_ARES_LIB=cares + PHP_ARES_LIBADD=rt + ], [ + PHP_CHECK_LIBRARY(ares, ares_init, [ + PHP_ARES_LIB=ares + PHP_ARES_LIBADD=rt + ], [ + PHP_AREES_LIB=unknown + ], [ + -lrt -L$PHP_ARES_DIR/$PHP_LIBDIR + ]) + ], [ + -lrt -L$PHP_ARES_DIR/$PHP_LIBDIR + ]) ], [ - -lrt -L$PHP_ARES_DIR/$PHP_LIBDIR + -L$PHP_ARES_DIR/$PHP_LIBDIR ] ) ], [ - -lrt -L$PHP_ARES_DIR/$PHP_LIBDIR + -L$PHP_ARES_DIR/$PHP_LIBDIR ] ) AC_MSG_CHECKING(for libares/libcares) AC_MSG_RESULT($PHP_ARES_LIB) + if test "x$PHP_ARES_LIBADD" != "x"; then + PHP_ADD_LIBRARY(PHP_ARES_LIBADD, 1, ARES_SHARED_LIBADD) + dnl for later use + PHP_ARES_LIBADD="-l$PHP_ARES_LIBADD" + fi + if test $PHP_ARES_LIB = "unknown"; then AC_MSG_ERROR(could neither find libares nor libcares) elif test $PHP_ARES_LIB = "cares"; then @@ -55,27 +71,39 @@ if test "$PHP_ARES" != "no"; then PHP_CHECK_LIBRARY($PHP_ARES_LIB, ares_cancel, [AC_DEFINE([HAVE_ARES_CANCEL], [1], [ ])], [ ], - [-lrt -L$PHP_ARES_DIR/$PHP_LIBDIR] + [$PHP_ARES_LIBADD -L$PHP_ARES_DIR/$PHP_LIBDIR] ) PHP_CHECK_LIBRARY($PHP_ARES_LIB, ares_getnameinfo, [AC_DEFINE([HAVE_ARES_GETNAMEINFO], [1], [ ])], [ ], - [-lrt -L$PHP_ARES_DIR/$PHP_LIBDIR] + [$PHP_ARES_LIBADD -L$PHP_ARES_DIR/$PHP_LIBDIR] ) PHP_CHECK_LIBRARY($PHP_ARES_LIB, ares_getsock, [AC_DEFINE([HAVE_ARES_GETSOCK], [1], [ ])], [ ], - [-lrt -L$PHP_ARES_DIR/$PHP_LIBDIR] + [$PHP_ARES_LIBADD -L$PHP_ARES_DIR/$PHP_LIBDIR] ) PHP_CHECK_LIBRARY($PHP_ARES_LIB, ares_version, [AC_DEFINE([HAVE_ARES_VERSION], [1], [ ])], [ ], - [-lrt -L$PHP_ARES_DIR/$PHP_LIBDIR] + [$PHP_ARES_LIBADD -L$PHP_ARES_DIR/$PHP_LIBDIR] ) PHP_CHECK_LIBRARY($PHP_ARES_LIB, ares_library_init, [AC_DEFINE([HAVE_ARES_LIBRARY_INIT], [1], [ ])], [ ], - [-lrt -L$PHP_ARES_DIR/$PHP_LIBDIR] + [$PHP_ARES_LIBADD -L$PHP_ARES_DIR/$PHP_LIBDIR] ) PHP_CHECK_LIBRARY($PHP_ARES_LIB, ares_library_cleanup, [AC_DEFINE([HAVE_ARES_LIBRARY_CLEANUP], [1], [ ])], [ ], - [-lrt -L$PHP_ARES_DIR/$PHP_LIBDIR] + [$PHP_ARES_LIBADD -L$PHP_ARES_DIR/$PHP_LIBDIR] + ) + PHP_CHECK_LIBRARY($PHP_ARES_LIB, ares_set_local_dev, + [AC_DEFINE([HAVE_ARES_SET_LOCAL_DEV], [1], [ ])], [ ], + [$PHP_ARES_LIBADD -L$PHP_ARES_DIR/$PHP_LIBDIR] + ) + PHP_CHECK_LIBRARY($PHP_ARES_LIB, ares_set_local_ip4, + [AC_DEFINE([HAVE_ARES_SET_LOCAL_IP4], [1], [ ])], [ ], + [$PHP_ARES_LIBADD -L$PHP_ARES_DIR/$PHP_LIBDIR] + ) + PHP_CHECK_LIBRARY($PHP_ARES_LIB, ares_set_local_ip6, + [AC_DEFINE([HAVE_ARES_SET_LOCAL_IP6], [1], [ ])], [ ], + [$PHP_ARES_LIBADD -L$PHP_ARES_DIR/$PHP_LIBDIR] ) dnl ########## @@ -83,7 +111,7 @@ if test "$PHP_ARES" != "no"; then dnl ########## save_LIBS=$LIBS save_CFLAGS=$CFLAGS - LDFLIBS="-L$PHP_ARES_DIR/$PHP_LIBDIR -l$PHP_ARES_LIB -lrt" + LIBS="-L$PHP_ARES_DIR/$PHP_LIBDIR -l$PHP_ARES_LIB $PHP_ARES_LIBADD" CFLAGS="-I$PHP_ARES_DIR/include -Werror" AC_MSG_CHECKING(for new c-ares callback API) @@ -109,5 +137,5 @@ if test "$PHP_ARES" != "no"; then PHP_ADD_LIBRARY_WITH_PATH($PHP_ARES_LIB, $PHP_ARES_DIR/$PHP_LIBDIR, ARES_SHARED_LIBADD) PHP_SUBST(ARES_SHARED_LIBADD) - PHP_NEW_EXTENSION(ares, ares.c, $ext_shared) + PHP_NEW_EXTENSION(ares, php_ares.c, $ext_shared) fi diff --git a/package.xml b/package.xml index affbd1b..aa9d9d8 100644 --- a/package.xml +++ b/package.xml @@ -23,8 +23,8 @@ 2009-12-23 - 0.7.0 - 0.7.0 + 0.8.0 + 0.8.0 beta @@ -32,7 +32,7 @@ BSD, revised @@ -40,7 +40,7 @@ - + diff --git a/php_ares.c b/php_ares.c new file mode 100644 index 0000000..1685d43 --- /dev/null +++ b/php_ares.c @@ -0,0 +1,2172 @@ +/* + +--------------------------------------------------------------------+ + | PECL :: ares | + +--------------------------------------------------------------------+ + | Redistribution and use in source and binary forms, with or without | + | modification, are permitted provided that the conditions mentioned | + | in the accompanying LICENSE file are met. | + +--------------------------------------------------------------------+ + | Copyright (c) 2006, Michael Wallner | + +--------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_ares.h" + +#include +#ifdef HAVE_ARES_VERSION +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif +#ifdef HAVE_ARPA_NAMESER_H +# include +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +# include +#endif + +#define local static inline + +#ifndef ZEND_ENGINE_2 +# define PHP_ARES_IS_CALLABLE(a,b,c) 1 +# ifndef ZTS +# undef TSRMLS_SET_CTX +# define TSRMLS_SET_CTX +# undef TSRMLS_FETCH_FROM_CTX +# define TSRMLS_FETCH_FROM_CTX +# endif +#endif +#if (PHP_MAJOR_VERSION > 5) || ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3)) +# define ADDREF(z) Z_ADDREF_P(z) +# define PHP_ARES_IS_CALLABLE(a,b,c) zend_is_callable((a), (b), (c) TSRMLS_CC) +#else +# define ADDREF(z) ZVAL_ADDREF(z) +# define PHP_ARES_IS_CALLABLE(a,b,c) zend_is_callable((a), (b), (c)) +#endif + +#define PHP_ARES_LE_NAME "AsyncResolver" +#define PHP_ARES_QUERY_LE_NAME "AsyncResolverQuery" +static int le_ares; +static int le_ares_query; + +static const char *php_ares_C_names[] = { + "INVALID", + "IN", + "CHAOS", + "HS", + "NONE", + "ANY", +}; + +static const char *php_ares_T_names[] = { + "INVALID", + "A", + "NS", + "MD", + "MF", + "CNAME", + "SOA", + "MB", + "MG", + "MR", + "NULL", + "WKS", + "PTR", + "HINFO", + "MINFO", + "MX", + "TXT", + "RP", + "AFSDB", + "X25", + "ISDN", + "RT", + "NSAP", + "NSAP_PTR", + "SIG", + "KEY", + "PX", + "GPOS", + "AAAA", + "LOC", + "NXT", + "EID", + "NIMLOC", + "SRV", + "ATMA", + "NAPTR", + "KX", + "CERT", + "A6", + "DNAME", + "SINK", + "OPT", + "APL", /* 42 */ + "","","","","","","","","","","","","","","","","","","","", /* 20x */ + "","","","","","","","","","","","","","","","","","","","", /* 20x */ + "","","","","","","","","","","","","","","","","","","","", /* 20x */ + "","","","","","","","","","","","","","","","","","","","", /* 20x */ + "","","","","","","","","","","","","","","","","","","","", /* 20x */ + "","","","","","","","","","","","","","","","","","","","", /* 20x */ + "","","","","","","","","","","","","","","","","","","","", /* 20x */ + "","","","","","","","","","","","","","","","","","","","", /* 20x */ + "","","","","","","","","","","","","","","","","","","","", /* 20x */ + "","","","","","","","","","","","","","","","","","","","", /* 20x */ + "","","","","","","","","","","","","","","","","","","","", /* 20x */ + "","","","","","","","","","","","","","","","","","","","", /* 20x */ + "","","","","","", /* 6x */ + "TKEY", /* 249 */ + "TSIG", + "IXFR", + "AXFR", + "MAILB", + "MAILA", + "ANY", /* 255 */ + "ZXFR", /* 256 */ +}; + +#ifdef HAVE_OLD_ARES_STRERROR +# define PHP_ARES_ERROR(err) { \ + char *__tmp = NULL; \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ares_strerror(err, &__tmp)); \ + if (__tmp) ares_free_errmem(__tmp); \ +} +#else +# define PHP_ARES_ERROR(err) \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ares_strerror(err)) +#endif + +#define RETURN_ARES_ERROR(err) \ + PHP_ARES_ERROR(err); \ + RETURN_FALSE +#define PHP_ARES_CB_ERROR(param) \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected the " param " argument to be a valid callback") +#define RETURN_ARES_CB_ERROR(param) \ + PHP_ARES_CB_ERROR(param); \ + RETURN_FALSE + +#define PHP_ARES_QUERY_BUFFER_LEN 2<<0xf + +/* {{{ typedefs */ +typedef struct _php_ares_options { + struct ares_options strct; + int flags; +} php_ares_options; + +typedef struct _php_ares { + ares_channel channel; + php_ares_options options; + zend_llist queries; + void ***tsrm_ls; + unsigned in_callback:1; + unsigned reserved:31; +} php_ares; + +typedef enum _php_ares_query_type { + PHP_ARES_CB_STD, + PHP_ARES_CB_HOST, + PHP_ARES_CB_NINFO, +} php_ares_query_type; + +typedef enum _php_ares_query_packet_type { + PHP_ARES_PCKT_SEARCH, + PHP_ARES_PCKT_QUERY, + PHP_ARES_PCKT_SEND, + PHP_ARES_PCKT_HNAME, + PHP_ARES_PCKT_HADDR, + PHP_ARES_PCKT_NINFO, +} php_ares_query_packet_type; + +typedef union _php_ares_query_packet_data { + struct { + char *name; + int name_len; + long type; + long dnsclass; + } search; + struct { + char *name; + int name_len; + long type; + long dnsclass; + } query; + struct { + char *buf; + int len; + } send; + struct { + char *name; + int name_len; + long family; + } hname; + struct { + char *addr; + int addr_len; + long family; + } haddr; + struct { + char *addr; + int addr_len; + long port; + long family; + long flags; + } ninfo; +} php_ares_query_packet_data; + +typedef struct _php_ares_query_packet { + php_ares_query_packet_type type; + php_ares_query_packet_data data; +} php_ares_query_packet; + +typedef union _php_ares_query_result { + struct { + zval *arr; + char *buf; + int len; + } std; + struct hostent host; + struct { + char *service; + char *node; + } ninfo; +} php_ares_query_result; + +typedef struct _php_ares_query { + int id; + int error; + php_ares *ares; + zval *callback; + php_ares_query_type type; + php_ares_query_packet packet; + php_ares_query_result result; +} php_ares_query; +/* }}} */ + +local struct hostent *php_ares_hostent_ctor(struct hostent *host) /* {{{ */ +{ + if (!host) { + host = emalloc(sizeof(struct hostent)); + } + memset(host, 0, sizeof(struct hostent)); + + return host; +} +/* }}} */ + +local void php_ares_hostent_copy(struct hostent *from, struct hostent *to) /* {{{ */ +{ + int i, c; + char **ptr; + + memcpy(to, from, sizeof(struct hostent)); + to->h_name = estrdup(from->h_name); + for (c = 0, ptr = from->h_aliases; *ptr; ++ptr, ++c); + to->h_aliases = ecalloc((c+1), sizeof(char *)); + for (i = 0; i < c; ++i) { + to->h_aliases[i] = estrdup(from->h_aliases[i]); + } + for (c = 0, ptr = from->h_addr_list; *ptr; ++ptr, ++c); + to->h_addr_list = ecalloc((c+1), sizeof(char *)); + for (i = 0; i < c; ++i) { + to->h_addr_list[i] = emalloc(from->h_length); + memcpy(to->h_addr_list[i], from->h_addr_list[i], from->h_length); + } +} +/* }}} */ + +local void php_ares_hostent_to_struct(struct hostent *hostent, HashTable *ht) /* {{{ */ +{ + zval array, *tmp; + char **ptr; + + INIT_PZVAL(&array); + Z_TYPE(array) = IS_ARRAY; + Z_ARRVAL(array) = ht; + + if (hostent) { + add_assoc_string(&array, "name", hostent->h_name, 1); + + MAKE_STD_ZVAL(tmp); + array_init(tmp); + if (hostent->h_aliases) { + for (ptr = hostent->h_aliases; *ptr; ++ptr) { + add_next_index_string(tmp, *ptr, 1); + } + } + add_assoc_zval(&array, "aliases", tmp); + add_assoc_long(&array, "addrtype", hostent->h_addrtype); + + MAKE_STD_ZVAL(tmp); + array_init(tmp); + if (hostent->h_addr_list) { + for (ptr = hostent->h_addr_list; *ptr; ++ptr) { + char name[64] = {0}; + + if (inet_ntop(hostent->h_addrtype, *ptr, name, sizeof(name)-1)) { + add_next_index_string(tmp, name, 1); + } + } + } + add_assoc_zval(&array, "addrlist", tmp); + } +} +/* }}} */ + +local void php_ares_hostent_dtor(struct hostent *host) /* {{{ */ +{ + char **ptr; + + STR_FREE(host->h_name); + if (host->h_aliases) { + for (ptr = host->h_aliases; *ptr; ++ptr) { + efree(*ptr); + } + efree(host->h_aliases); + } + if (host->h_addr_list) { + for (ptr = host->h_addr_list; *ptr; ++ptr) { + efree(*ptr); + } + efree(host->h_addr_list); + } + memset(host, 0, sizeof(struct hostent)); +} +/* }}} */ + +local void php_ares_hostent_free(struct hostent **host) /* {{{ */ +{ + php_ares_hostent_dtor(*host); + efree(*host); + *host = NULL; +} +/* }}} */ + +local php_ares_query *php_ares_query_ctor(php_ares_query *query, php_ares_query_type type, php_ares *ares, zval *callback) /* {{{ */ +{ + if (!query) { + query = emalloc(sizeof(php_ares_query)); + } + memset(query, 0, sizeof(php_ares_query)); + + query->ares = ares; + query->type = type; + query->error = -1; + + if (callback) { + ADDREF(callback); + query->callback = callback; + } + + return query; +} +/* }}} */ + +local void php_ares_query_rsrc(php_ares_query *query, zval *return_value) /* {{{ */ +{ + TSRMLS_FETCH_FROM_CTX(query->ares->tsrm_ls); + + ZEND_REGISTER_RESOURCE(return_value, query, le_ares_query); + query->id = Z_LVAL_P(return_value); + zend_list_addref(query->id); + zend_llist_add_element(&query->ares->queries, &query); +} +/* }}} */ + +local void php_ares_query_pckt(php_ares_query *query, php_ares_query_packet_type type, ...) +{ + va_list argv; + char *buf; + int len; + + va_start(argv, type); + + switch (query->packet.type = type) { + case PHP_ARES_PCKT_SEARCH: + buf = va_arg(argv, char *); + len = va_arg(argv, int); + query->packet.data.search.name = estrndup(buf, len); + query->packet.data.search.name_len = len; + query->packet.data.search.type = va_arg(argv, long); + query->packet.data.search.dnsclass = va_arg(argv, long); + break; + + case PHP_ARES_PCKT_QUERY: + buf = va_arg(argv, char *); + len = va_arg(argv, int); + query->packet.data.query.name = estrndup(buf, len); + query->packet.data.query.name_len = len; + query->packet.data.query.type = va_arg(argv, long); + query->packet.data.query.dnsclass = va_arg(argv, long); + break; + + case PHP_ARES_PCKT_SEND: + buf = va_arg(argv, char *); + len = va_arg(argv, int); + query->packet.data.send.buf = estrndup(buf, len); + query->packet.data.send.len = len; + break; + + case PHP_ARES_PCKT_HNAME: + buf = va_arg(argv, char *); + len = va_arg(argv, int); + query->packet.data.hname.name = estrndup(buf, len); + query->packet.data.hname.name_len = len; + query->packet.data.hname.family = va_arg(argv, long); + break; + + case PHP_ARES_PCKT_HADDR: + buf = va_arg(argv, char *); + len = va_arg(argv, int); + query->packet.data.haddr.addr = estrndup(buf, len); + query->packet.data.haddr.addr_len = len; + query->packet.data.haddr.family = va_arg(argv, long); + break; + + case PHP_ARES_PCKT_NINFO: + query->packet.data.ninfo.flags = va_arg(argv, long); + buf = va_arg(argv, char *); + len = va_arg(argv, int); + query->packet.data.ninfo.addr = estrndup(buf, len); + query->packet.data.ninfo.addr_len = len; + query->packet.data.ninfo.family = va_arg(argv, long); + query->packet.data.ninfo.port = va_arg(argv, long); + break; + } + + va_end(argv); +} + +local void php_ares_query_dtor(php_ares_query *query) /* {{{ */ +{ + struct php_ares_query_packet_buf {char *buf;} *packet; + + packet = (struct php_ares_query_packet_buf *) &query->packet.data; + if (packet->buf) { + efree(packet->buf); + } + switch (query->type) { + case PHP_ARES_CB_STD: + if (query->result.std.arr) { + zval_ptr_dtor(&query->result.std.arr); + } + STR_FREE(query->result.std.buf); + break; + case PHP_ARES_CB_HOST: + php_ares_hostent_dtor(&query->result.host); + break; + case PHP_ARES_CB_NINFO: + STR_FREE(query->result.ninfo.service); + STR_FREE(query->result.ninfo.node); + break; + } + if (query->callback) { + zval_ptr_dtor(&query->callback); + } + memset(query, 0, sizeof(php_ares_query)); +} +/* }}} */ + +local void php_ares_query_free(php_ares_query **query) /* {{{ */ +{ + php_ares_query_dtor(*query); + efree(*query); + *query = NULL; +} +/* }}} */ + +local php_ares_options *php_ares_options_ctor(php_ares_options *options, HashTable *ht) /* {{{ */ +{ + int i; + zval **opt, **entry; + + if (!options) { + options = emalloc(sizeof(php_ares_options)); + } + memset(options, 0, sizeof(php_ares_options)); + + if (ht && zend_hash_num_elements(ht)) { + if ((SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) { + options->flags |= ARES_OPT_FLAGS; + options->strct.flags = Z_LVAL_PP(opt); + } + if ((SUCCESS == zend_hash_find(ht, "timeout", sizeof("timeout"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) { + options->flags |= ARES_OPT_TIMEOUT; + options->strct.timeout = Z_LVAL_PP(opt); + } + if ((SUCCESS == zend_hash_find(ht, "tries", sizeof("tries"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) { + options->flags |= ARES_OPT_TRIES; + options->strct.tries = Z_LVAL_PP(opt); + } + if ((SUCCESS == zend_hash_find(ht, "ndots", sizeof("ndots"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) { + options->flags |= ARES_OPT_NDOTS; + options->strct.ndots = Z_LVAL_PP(opt); + } + if ((SUCCESS == zend_hash_find(ht, "udp_port", sizeof("udp_port"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) { + options->flags |= ARES_OPT_UDP_PORT; + options->strct.udp_port = htons((unsigned short) Z_LVAL_PP(opt)); + } + if ((SUCCESS == zend_hash_find(ht, "tcp_port", sizeof("tcp_port"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) { + options->flags |= ARES_OPT_TCP_PORT; + options->strct.tcp_port = htons((unsigned short) Z_LVAL_PP(opt)); + } + if ((SUCCESS == zend_hash_find(ht, "servers", sizeof("servers"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_ARRAY) && (i = zend_hash_num_elements(Z_ARRVAL_PP(opt)))) { + options->strct.servers = ecalloc(i, sizeof(struct in_addr)); + for ( zend_hash_internal_pointer_reset(Z_ARRVAL_PP(opt)); + 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++]); + } + } + if (options->strct.nservers) { + options->flags |= ARES_OPT_SERVERS; + } + } + if ((SUCCESS == zend_hash_find(ht, "domains", sizeof("domains"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_ARRAY) && (i = zend_hash_num_elements(Z_ARRVAL_PP(opt)))) { + options->strct.domains = ecalloc(i, sizeof(char *)); + for ( zend_hash_internal_pointer_reset(Z_ARRVAL_PP(opt)); + 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) { + options->strct.domains[options->strct.ndomains++] = estrdup(Z_STRVAL_PP(entry)); + } + } + if (options->strct.ndomains) { + options->flags |= ARES_OPT_DOMAINS; + } + } + if ((SUCCESS == zend_hash_find(ht, "lookups", sizeof("lookups"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_STRING)) { + options->flags |= ARES_OPT_LOOKUPS; + options->strct.lookups = estrdup(Z_STRVAL_PP(opt)); + } + } + + return options; +} +/* }}} */ + +local void php_ares_options_dtor(php_ares_options *options) /* {{{ */ +{ + int i; + + if (options->strct.servers) { + efree(options->strct.servers); + } + + if (options->strct.domains) { + for (i = 0; i < options->strct.ndomains; ++i) { + efree(options->strct.domains[i]); + } + efree(options->strct.domains); + } + + STR_FREE(options->strct.lookups); + + memset(options, 0, sizeof(php_ares_options)); +} +/* }}} */ + +local void php_ares_options_free(php_ares_options **options) /* {{{ */ +{ + php_ares_options_dtor(*options); + efree(*options); + *options = NULL; +} +/* }}} */ + +local PHP_ARES_EXPAND_LEN_TYPE php_ares_skip(const unsigned char *pointer, const unsigned char *abuf, int alen TSRMLS_DC) +{ + char *name; + int rc; + PHP_ARES_EXPAND_LEN_TYPE byte_count; + + /* NOTE: byte_count is not neccessarily the length of the string, + i.e. if there were back references */ + if (ARES_SUCCESS == (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) { + /*fprintf(stderr, "-- skipping %s\n", name);*/ + ares_free_string(name); + return byte_count; + } + PHP_ARES_ERROR(rc); + return -1; +} + +local int php_ares_parse(const unsigned char *abuf, int alen, zval *result TSRMLS_DC) /* {{{ */ +{ + HEADER *header; + PHP_ARES_EXPAND_LEN_TYPE byte_count; + const unsigned char *pointer; + char *name; + int rc, query_count, answer_count; + + convert_to_array(result); + + if (!alen || !abuf || !*abuf) { + return SUCCESS; + } + + header = (HEADER *) abuf; + pointer = abuf + HFIXEDSZ; + + for (query_count = ntohs(header->qdcount); query_count--; pointer += byte_count + QFIXEDSZ) { + if (0 > (byte_count = php_ares_skip(pointer, abuf, alen TSRMLS_CC))) { + return FAILURE; + } + } + + 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; + + if (0 > (byte_count = php_ares_skip(pointer, abuf, alen TSRMLS_CC))) { + return FAILURE; + } + + pointer += byte_count; + + MAKE_STD_ZVAL(entry); + array_init(entry); + + GETSHORT(type, pointer); + add_assoc_string(entry, "type", estrdup(php_ares_T_names[type]), 0); + GETSHORT(class, pointer); + add_assoc_string(entry, "class", estrdup(php_ares_C_names[class]), 0); + GETLONG(ttl, pointer); + add_assoc_long(entry, "ttl", ttl); + GETSHORT(byte_count, pointer); +#if 0 + fprintf(stderr, ">> processing %s answer of length %d\n", php_ares_T_names[type], byte_count); +#endif + switch (type) { + case T_A: + spprintf(&name, 0, "%d.%d.%d.%d", pointer[0], pointer[1], pointer[2], pointer[3]); + add_assoc_string(entry, "addr", name, 0); + pointer += byte_count; + break; + + case T_NS: + case T_PTR: + case T_CNAME: + if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) { + PHP_ARES_ERROR(rc); + return FAILURE; + } + pointer += byte_count; + add_assoc_string(entry, "name", name, 1); + ares_free_string(name); + break; + + case T_MX: + GETSHORT(stmp, pointer); + if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) { + PHP_ARES_ERROR(rc); + return FAILURE; + } + pointer += byte_count; + add_assoc_long(entry, "weight", stmp); + add_assoc_string(entry, "name", name, 1); + ares_free_string(name); + break; + + case T_SRV: + GETSHORT(stmp, pointer); + add_assoc_long(entry, "priority", stmp); + GETSHORT(stmp, pointer); + add_assoc_long(entry, "weight", stmp); + GETSHORT(stmp, pointer); + add_assoc_long(entry, "port", stmp); + + if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) { + PHP_ARES_ERROR(rc); + zval_ptr_dtor(&entry); + return FAILURE; + } + pointer += byte_count; + add_assoc_string(entry, "name", name, 1); + ares_free_string(name); + break; + + case T_SOA: + if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) { + PHP_ARES_ERROR(rc); + zval_ptr_dtor(&entry); + return FAILURE; + } + pointer += byte_count; + add_assoc_string(entry, "name", name, 1); + ares_free_string(name); + + if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) { + PHP_ARES_ERROR(rc); + zval_ptr_dtor(&entry); + return FAILURE; + } + pointer += byte_count; + add_assoc_string(entry, "mail", name, 1); + ares_free_string(name); + + GETLONG(ltmp, pointer); + add_assoc_long(entry, "serial", ltmp); + GETLONG(ltmp, pointer); + add_assoc_long(entry, "refresh", ltmp); + GETLONG(ltmp, pointer); + add_assoc_long(entry, "retry", ltmp); + GETLONG(ltmp, pointer); + add_assoc_long(entry, "expire", ltmp); + GETLONG(ltmp, pointer); + add_assoc_long(entry, "minimum-ttl", ltmp); + break; + + case T_TXT: + for (ltmp = 0; ltmp < byte_count; ltmp += pointer[ltmp] + 1) { + add_next_index_stringl(entry, (const char *) &pointer[ltmp + 1], pointer[ltmp], 1); + } + pointer += byte_count; + break; + + default: + zval_ptr_dtor(&entry); + entry = NULL; + pointer += byte_count; + break; + } + + if (entry) { + add_next_index_zval(result, entry); + } + } + + return SUCCESS; +} +/* }}} */ + +/* {{{ callbacks */ +static void php_ares_callback_func_old(void *aq, int status, unsigned char *abuf, int alen) +{ + php_ares_query *q = (php_ares_query *) aq; + zval *params[4], *retval, *parsed = NULL; + TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls); + + q->error = status; + if (abuf) { + q->result.std.buf = estrndup((char *) abuf, alen); + q->result.std.len = alen; + + MAKE_STD_ZVAL(parsed); + ZVAL_NULL(parsed); + if (SUCCESS == php_ares_parse(abuf, alen, parsed)) { + q->result.std.arr = parsed; + } else { + zval_ptr_dtor(&parsed); + parsed = NULL; + } + } + + if (q->callback) { + MAKE_STD_ZVAL(retval); + MAKE_STD_ZVAL(params[0]); + MAKE_STD_ZVAL(params[1]); + MAKE_STD_ZVAL(params[2]); + ZVAL_NULL(retval); + zend_list_addref(q->id); + Z_LVAL_P(params[0]) = q->id; + Z_TYPE_P(params[0]) = IS_RESOURCE; + ZVAL_LONG(params[1], status); + ZVAL_STRINGL(params[2], (char *) abuf, alen, 1); + + if (parsed) { + ADDREF(parsed); + params[3] = parsed; + } + + q->ares->in_callback = 1; + call_user_function(EG(function_table), NULL, q->callback, retval, parsed ? 4 : 3, params TSRMLS_CC); + q->ares->in_callback = 0; + + zval_ptr_dtor(&retval); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + + if (parsed) { + zval_ptr_dtor(¶ms[3]); + } + } +} + +static void php_ares_host_callback_func_old(void *aq, int status, struct hostent *hostent) +{ + php_ares_query *q = (php_ares_query *) aq; + zval *params[3], *retval; + TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls); + + q->error = status; + if (hostent) { + php_ares_hostent_copy(hostent, &q->result.host); + } + + if (q->callback) { + MAKE_STD_ZVAL(retval); + MAKE_STD_ZVAL(params[0]); + MAKE_STD_ZVAL(params[1]); + MAKE_STD_ZVAL(params[2]); + ZVAL_NULL(retval); + zend_list_addref(q->id); + Z_LVAL_P(params[0]) = q->id; + Z_TYPE_P(params[0]) = IS_RESOURCE; + ZVAL_LONG(params[1], status); + object_init(params[2]); + php_ares_hostent_to_struct(hostent, HASH_OF(params[2])); + + q->ares->in_callback = 1; + call_user_function(EG(function_table), NULL, q->callback, retval, 3, params TSRMLS_CC); + q->ares->in_callback = 0; + + zval_ptr_dtor(&retval); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + } +} + +#ifdef HAVE_ARES_GETNAMEINFO +static void php_ares_nameinfo_callback_func_old(void *aq, int status, char *node, char *service) +{ + php_ares_query *q = (php_ares_query *) aq; + zval *params[4], *retval; + TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls); + + q->error = status; + if (node) { + q->result.ninfo.node = estrdup(node); + } + if (service) { + q->result.ninfo.service = estrdup(service); + } + + if (q->callback) { + MAKE_STD_ZVAL(retval); + MAKE_STD_ZVAL(params[0]); + MAKE_STD_ZVAL(params[1]); + MAKE_STD_ZVAL(params[2]); + MAKE_STD_ZVAL(params[3]); + ZVAL_NULL(retval); + zend_list_addref(q->id); + Z_LVAL_P(params[0]) = q->id; + Z_TYPE_P(params[0]) = IS_RESOURCE; + ZVAL_LONG(params[1], status); + if (node) { + ZVAL_STRING(params[2], node, 1); + } else { + ZVAL_NULL(params[2]); + } + if (service) { + ZVAL_STRING(params[3], service, 1); + } else { + ZVAL_NULL(params[3]); + } + + q->ares->in_callback = 1; + call_user_function(EG(function_table), NULL, q->callback, retval, 4, params TSRMLS_CC); + q->ares->in_callback = 0; + + zval_ptr_dtor(&retval); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + } +} +#endif + +#if PHP_ARES_NEW_CALLBACK_API +# define php_ares_callback_func php_ares_callback_func_new +static void php_ares_callback_func_new(void *aq, int status, int timeouts, unsigned char *abuf, int alen) +{ + php_ares_callback_func_old(aq, status, abuf, alen); +} + +# define php_ares_host_callback_func php_ares_host_callback_func_new +static void php_ares_host_callback_func_new(void *aq, int status, int timeouts, struct hostent *hostent) +{ + php_ares_host_callback_func_old(aq, status, hostent); +} + +# ifdef HAVE_ARES_GETNAMEINFO +# define php_ares_nameinfo_callback_func php_ares_nameinfo_callback_func_new +static void php_ares_nameinfo_callback_func_new(void *aq, int status, int timeouts, char *node, char *service) +{ + php_ares_nameinfo_callback_func_old(aq, status, node, service); +} +# endif + +#else +# define php_ares_callback_func php_ares_callback_func_old +# define php_ares_host_callback_func php_ares_host_callback_func_old +# ifdef HAVE_ARES_GETNAMEINFO +# define php_ares_nameinfo_callback_func php_ares_nameinfo_callback_func_old +# endif +#endif +/* }}} */ + +local struct timeval *php_ares_timeout(php_ares *ares, long max_timeout, struct timeval *tv_buf) /* {{{ */ +{ + struct timeval maxtv; + + if (max_timeout > -1) { + maxtv.tv_sec = max_timeout / 1000; + maxtv.tv_usec = max_timeout % (max_timeout * 1000); + } + + return ares_timeout(ares->channel, max_timeout > -1 ? &maxtv : NULL, tv_buf); +} +/* }}} */ + +local int php_ares_process(php_ares *ares, long max_timeout) /* {{{ */ +{ + int nfds; + fd_set R, W; + struct timeval tv; + + FD_ZERO(&R); + FD_ZERO(&W); + + if ((nfds = ares_fds(ares->channel, &R, &W))) { + if (0 < select(nfds, &R, &W, NULL, php_ares_timeout(ares, max_timeout, &tv))) { + ares_process(ares->channel, &R, &W); + } + } + + return nfds; +} +/* }}} */ + +local int php_ares_publish_fds(fd_set *R, fd_set *W, zval *r, zval *w) /* {{{ */ +{ + int i, nfds = 0; + + for (i = 0; i < FD_SETSIZE; ++i) { + if (FD_ISSET(i, R)) { + add_next_index_long(r, i); + if (i > nfds) { + nfds = i; + } + } + } + + for (i = 0; i < FD_SETSIZE; ++i) { + if (FD_ISSET(i, W)) { + add_next_index_long(w, i); + if (i > nfds) { + nfds = i; + } + } + } + + return nfds ? nfds + 1 : 0; +} +/* }}} */ + +local int php_ares_extract_fds(zval *r, zval *w, fd_set *R, fd_set *W) /* {{{ */ +{ + zval **fd; + int nfds = 0; + + 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) { + FD_SET(Z_LVAL_PP(fd), R); + if (Z_LVAL_PP(fd) > nfds) { + nfds = Z_LVAL_PP(fd); + } + } + } + } + + if (w && zend_hash_num_elements(Z_ARRVAL_P(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) { + FD_SET(Z_LVAL_PP(fd), W); + if (Z_LVAL_PP(fd) > nfds) { + nfds = Z_LVAL_PP(fd); + } + } + } + } + + return nfds ? nfds + 1 : 0; +} +/* }}} */ + +static void php_ares_query_llist_dtor(void *entry) +{ + php_ares_query *q = *(php_ares_query **) entry; + TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls); + zend_list_delete(q->id); +} + +#ifdef HAVE_ARES_VERSION +/* {{{ proto string ares_version() + Get libares version */ +static PHP_FUNCTION(ares_version) +{ + if (ZEND_NUM_ARGS()) { + WRONG_PARAM_COUNT; + } + + RETURN_STRING(estrdup(ares_version(NULL)), 0); +} +/* }}} */ +#endif + +/* {{{ proto resource ares_init([array options]) + Create an ares resource */ +static PHP_FUNCTION(ares_init) +{ + zval *opt_array = NULL; + php_ares *ares = NULL; + int err; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &opt_array)) { + RETURN_FALSE; + } + + ares = emalloc(sizeof(php_ares)); + TSRMLS_SET_CTX(ares->tsrm_ls); + zend_llist_init(&ares->queries, sizeof(php_ares_query *), (llist_dtor_func_t) php_ares_query_llist_dtor, 0); + php_ares_options_ctor(&ares->options, opt_array ? Z_ARRVAL_P(opt_array) : NULL); + + if (ARES_SUCCESS != (err = ares_init_options(&ares->channel, &ares->options.strct, ares->options.flags))) { + php_ares_options_dtor(&ares->options); + zend_llist_destroy(&ares->queries); + efree(ares); + RETURN_ARES_ERROR(err); + } + + ZEND_REGISTER_RESOURCE(return_value, ares, le_ares); +} +/* }}} */ + +/* {{{ proto void ares_destroy(resource ares) + Destroy the ares handle */ +static PHP_FUNCTION(ares_destroy) +{ + zval *rsrc; + php_ares *ares; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) { + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + if (ares->in_callback) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot destroy ares handle while in callback"); + } else { + zend_list_delete(Z_LVAL_P(rsrc)); + } + } +} +/* }}} */ + +/* {{{ proto string ares_strerror(int status) + Get description of status code */ +static PHP_FUNCTION(ares_strerror) +{ + long err; +#ifdef HAVE_OLD_ARES_STRERROR + char *__tmp = NULL; + const char *__err; +#endif + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &err)) { + RETURN_FALSE; + } + +#ifdef HAVE_OLD_ARES_STRERROR + __err = ares_strerror(err, &__tmp); + RETVAL_STRING(estrdup(__err), 0); + if (__tmp) { + ares_free_errmem(__tmp); + } +#else + RETURN_STRING(estrdup(ares_strerror(err)), 0); +#endif +} +/* }}} */ + +/* {{{ proto string ares_mkquery(string name, int dnsclass, int type, int id, int rd) + Compose a custom query */ +static PHP_FUNCTION(ares_mkquery) +{ + char *name_str, *query_str; + int name_len, query_len, err; + long dnsclass, type, id, rd; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sllll", &name_str, &name_len, &dnsclass, &type, &id, &rd)) { + RETURN_FALSE; + } + + if (ARES_SUCCESS != (err = ares_mkquery(name_str, dnsclass, type, id, rd, (unsigned char **) &query_str, &query_len))) { + RETURN_ARES_ERROR(err); + } + RETVAL_STRINGL(query_str, query_len, 1); + ares_free_string(query_str); +} +/* }}} */ + +/* {{{ proto resource ares_search(resource ares, mixed callback, string name[, int type = ARES_T_A[, int dnsclass = ARES_C_IN]]) + Issue a domain search for name */ +static PHP_FUNCTION(ares_search) +{ + zval *rsrc, *cb = NULL; + php_ares *ares; + php_ares_query *query; + char *name; + int name_len; + long dnsclass = C_IN, type = T_A; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|ll", &rsrc, &cb, &name, &name_len, &type, &dnsclass)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + + if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) { + RETURN_ARES_CB_ERROR("second"); + } + + query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb); + php_ares_query_rsrc(query, return_value); + php_ares_query_pckt(query, PHP_ARES_PCKT_SEARCH, name, name_len, type, dnsclass); + ares_search(ares->channel, name, dnsclass, type, php_ares_callback_func, query); +} +/* }}} */ + +/* {{{ proto resource ares_query(resource ares, mixed callback, string name[, int type = ARES_T_A[, int dnsclass = ARES_C_IN]]) + Issue a single DNS query */ +static PHP_FUNCTION(ares_query) +{ + zval *rsrc, *cb = NULL; + php_ares *ares; + php_ares_query *query; + char *name; + int name_len; + long dnsclass = C_IN, type = T_A; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|ll", &rsrc, &cb, &name, &name_len, &type, &dnsclass)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + + if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) { + RETURN_ARES_CB_ERROR("second"); + } + + query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb); + php_ares_query_rsrc(query, return_value); + php_ares_query_pckt(query, PHP_ARES_PCKT_QUERY, name, name_len, type, dnsclass); + ares_query(ares->channel, name, dnsclass, type, php_ares_callback_func, query); +} +/* }}} */ + +/* {{{ proto resource ares_send(resource ares, mixed callback, string buf) + Send custom query */ +static PHP_FUNCTION(ares_send) +{ + zval *rsrc, *cb = NULL; + php_ares *ares; + php_ares_query *query; + char *buf; + int len; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s", &rsrc, &cb, &buf, &len)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + + if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) { + RETURN_ARES_CB_ERROR("second"); + } + + query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb); + php_ares_query_rsrc(query, return_value); + php_ares_query_pckt(query, PHP_ARES_PCKT_SEND, buf, len); + ares_send(ares->channel, (const unsigned char *) buf, len, php_ares_callback_func, query); +} +/* }}} */ + +/* {{{ proto resource ares_gethostbyname(resource ares, mixed callback, string name[, int family = AF_INET]) + Get host by name */ +static PHP_FUNCTION(ares_gethostbyname) +{ + zval *rsrc, *cb = NULL; + php_ares *ares; + php_ares_query *query; + char *name; + int name_len; + long family = AF_INET; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|l", &rsrc, &cb, &name, &name_len, &family)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + + if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) { + RETURN_ARES_CB_ERROR("second"); + } + + query = php_ares_query_ctor(NULL, PHP_ARES_CB_HOST, ares, cb); + php_ares_query_rsrc(query, return_value); + php_ares_query_pckt(query, PHP_ARES_PCKT_HNAME, name, name_len, family); + ares_gethostbyname(ares->channel, name, family, php_ares_host_callback_func, query); +} +/* }}} */ + +/* {{{ proto resource ares_gethostbyaddr(resuorce ares, mixed callback, string address[, int family = ARES_AF_INET]) + Get host by address */ +static PHP_FUNCTION(ares_gethostbyaddr) +{ + zval *rsrc, *cb = NULL; + php_ares *ares; + php_ares_query *query; + char *addr; + int addr_len; + long family = AF_INET; + void *sa; + int sa_len; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|l", &rsrc, &cb, &addr, &addr_len, &family)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + + if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) { + PHP_ARES_CB_ERROR("second"); + RETURN_FALSE; + } + + switch (family) { + case AF_INET: + sa = emalloc(sa_len = sizeof(struct in_addr)); + break; + case AF_INET6: + sa = emalloc(sa_len = sizeof(struct in6_addr)); + break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter family is neither ARES_AF_INET nor ARES_AF_INET6"); + RETURN_FALSE; + break; + } + + if (1 > inet_pton(family, addr, sa)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr); + RETVAL_FALSE; + } else { + query = php_ares_query_ctor(NULL, PHP_ARES_CB_HOST, ares, cb); + php_ares_query_rsrc(query, return_value); + php_ares_query_pckt(query, PHP_ARES_PCKT_HADDR, addr, addr_len, family); + ares_gethostbyaddr(ares->channel, sa, sa_len, family, php_ares_host_callback_func, query); + } + efree(sa); +} +/* }}} */ + +#ifdef HAVE_ARES_GETNAMEINFO +/* {{{ proto resource ares_getnameinfo(resource ares, mixed callback, int flags, string addr[, int family = ARES_AF_INET[, int port = 0]]) + Get name info */ +static PHP_FUNCTION(ares_getnameinfo) +{ + zval *rsrc, *cb = NULL; + php_ares *ares; + php_ares_query *query; + char *addr; + int addr_len; + long flags, port = 0, family = AF_INET; + struct sockaddr *sa; + struct sockaddr_in *in; + struct sockaddr_in6 *in6; + int sa_len; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!ls|ll", &rsrc, &cb, &flags, &addr, &addr_len, &family, &port)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + + if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) { + PHP_ARES_CB_ERROR("second"); + RETURN_FALSE; + } + + RETVAL_TRUE; + switch (family) { + case AF_INET: + in = ecalloc(1, sa_len = sizeof(struct sockaddr_in)); + in->sin_family = AF_INET; + in->sin_port = htons((unsigned short) port); + if (1 > inet_pton(in->sin_family, addr, &in->sin_addr)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr); + RETVAL_FALSE; + } + sa = (struct sockaddr *) in; + break; + case AF_INET6: + in6 = ecalloc(1, sa_len = sizeof(struct sockaddr_in6)); + in6->sin6_family = AF_INET6; + in6->sin6_port = htons((unsigned short) port); + if (1 > inet_pton(in6->sin6_family, addr, &in6->sin6_addr)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr); + RETVAL_FALSE; + } + sa = (struct sockaddr *) in6; + break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter family is neither AF_INET nor AF_INET6"); + RETURN_FALSE; + break; + } + + if (Z_BVAL_P(return_value)) { + query = php_ares_query_ctor(NULL, PHP_ARES_CB_NINFO, ares, cb); + php_ares_query_rsrc(query, return_value); + php_ares_query_pckt(query, PHP_ARES_PCKT_NINFO, flags, addr, addr_len, family, port); + ares_getnameinfo(ares->channel, sa, sa_len, flags, php_ares_nameinfo_callback_func, query); + } + efree(sa); +} +/* }}} */ +#endif + +/* {{{ proto mixed ares_result(resource query, int &errno, string &error) + Check a query for its result */ +static PHP_FUNCTION(ares_result) +{ + zval *rsrc, *zerrno = NULL, *zerror = NULL; + php_ares_query *query; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|zz", &rsrc, &zerrno, &zerror)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(query, php_ares_query *, &rsrc, -1, PHP_ARES_QUERY_LE_NAME, le_ares_query); + + if (zerrno) { + zval_dtor(zerrno); + ZVAL_LONG(zerrno, query->error); + } + if (zerror) { + zval_dtor(zerror); + ZVAL_NULL(zerror); + } + + switch (query->error) { + case 0: + switch (query->type) { + case PHP_ARES_CB_STD: + if (query->result.std.arr) { + RETVAL_ZVAL(query->result.std.arr, 1, 0); + } else { + RETVAL_STRINGL(query->result.std.buf, query->result.std.len, 1); + } + break; + case PHP_ARES_CB_HOST: + object_init(return_value); + php_ares_hostent_to_struct(&query->result.host, HASH_OF(return_value)); + break; + case PHP_ARES_CB_NINFO: + object_init(return_value); + add_property_string(return_value, "node", query->result.ninfo.node ? query->result.ninfo.node : "", 1); + add_property_string(return_value, "service", query->result.ninfo.service ? query->result.ninfo.service : "", 1); + break; + } + break; + case -1: + RETVAL_FALSE; + break; + default: + if (zerror) { +#ifdef HAVE_OLD_ARES_STRERROR + char *__tmp = NULL; + const char *__err = ares_strerror(query->error, &__tmp); + ZVAL_STRING(zerror, estrdup(__err), 0); + if (__tmp) ares_free_errmem(__tmp); +#else + ZVAL_STRING(zerror, estrdup(ares_strerror(query->error)), 0); +#endif + } + RETVAL_FALSE; + break; + } +} +/* }}} */ + +/* {{{ proto object ares_packet(resource query) + Check a query for its question packet */ +static PHP_FUNCTION(ares_packet) +{ + zval *rsrc, *prop; + php_ares_query *query; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(query, php_ares_query *, &rsrc, -1, PHP_ARES_QUERY_LE_NAME, le_ares_query); + + object_init(return_value); + add_property_long(return_value, "type", query->packet.type); + add_property_null(return_value, "search"); + add_property_null(return_value, "query"); + add_property_null(return_value, "send"); + add_property_null(return_value, "gethostbyname"); + add_property_null(return_value, "gethostbyaddr"); + add_property_null(return_value, "getnameinfo"); + MAKE_STD_ZVAL(prop); + + switch (query->packet.type) { + case PHP_ARES_PCKT_SEARCH: + object_init(prop); + add_property_stringl(prop, "name", query->packet.data.search.name, query->packet.data.search.name_len, 1); + add_property_long(prop, "type", query->packet.data.search.type); + add_property_long(prop, "dnsclass", query->packet.data.search.dnsclass); + add_property_zval(return_value, "search", prop); + break; + + case PHP_ARES_PCKT_QUERY: + object_init(prop); + add_property_stringl(prop, "name", query->packet.data.query.name, query->packet.data.query.name_len, 1); + add_property_long(prop, "type", query->packet.data.query.type); + add_property_long(prop, "dnsclass", query->packet.data.query.dnsclass); + add_property_zval(return_value, "query", prop); + break; + + case PHP_ARES_PCKT_SEND: + ZVAL_STRINGL(prop, query->packet.data.send.buf, query->packet.data.send.len, 1); + add_property_zval(return_value, "send", prop); + break; + + case PHP_ARES_PCKT_HNAME: + object_init(prop); + add_property_stringl(prop, "name", query->packet.data.hname.name, query->packet.data.hname.name_len, 1); + add_property_long(prop, "family", query->packet.data.hname.family); + add_property_zval(return_value, "gethostbyname", prop); + break; + + case PHP_ARES_PCKT_HADDR: + object_init(prop); + add_property_stringl(prop, "addr", query->packet.data.haddr.addr, query->packet.data.haddr.addr_len, 1); + add_property_long(prop, "family", query->packet.data.haddr.family); + add_property_zval(return_value, "gethostbyaddr", prop); + break; + + case PHP_ARES_PCKT_NINFO: + object_init(prop); + add_property_long(prop, "flags", query->packet.data.ninfo.flags); + add_property_stringl(prop, "addr", query->packet.data.ninfo.addr, query->packet.data.ninfo.addr_len, 1); + add_property_long(prop, "family", query->packet.data.ninfo.family); + add_property_long(prop, "port", query->packet.data.ninfo.port); + add_property_zval(return_value, "getnameinfo", prop); + break; + } + + zval_ptr_dtor(&prop); +} +/* }}} */ + +#ifdef HAVE_ARES_CANCEL +/* {{{ proto void ares_cancel(resource ares) + Cancel pending queries */ +static PHP_FUNCTION(ares_cancel) +{ + zval *rsrc; + php_ares *ares; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) { + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + ares_cancel(ares->channel); + } +} +/* }}} */ +#endif + +/* {{{ proto void ares_process_all(resource ares[, int max_timeout_ms]) + Process all pending queries */ +static PHP_FUNCTION(ares_process_all) +{ + zval *rsrc; + php_ares *ares; + long max_timeout = -1; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + + while (php_ares_process(ares, max_timeout)); +} +/* }}} */ + +/* {{{ proto bool ares_process_once(resource ares[, int max_timout_ms]) + Process once and return whether it should be called again */ +static PHP_FUNCTION(ares_process_once) +{ + zval *rsrc; + php_ares *ares; + long max_timeout = -1; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + + RETVAL_BOOL(php_ares_process(ares, max_timeout)); +} +/* }}} */ + +/* {{{ proto void ares_process(resource ares, array read, array write) + Process call */ +static PHP_FUNCTION(ares_process) +{ + zval *rsrc, *read = NULL, *write = NULL; + fd_set R, W; + php_ares *ares; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|a!a!", &rsrc, &read, &write)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + + FD_ZERO(&R); + FD_ZERO(&W); + + php_ares_extract_fds(read, write, &R, &W); + ares_process(ares->channel, &R, &W); +} +/* }}} */ + +/* proto bool ares_select(array &read, array &write, int timeout_ms) + Select call */ +static PHP_FUNCTION(ares_select) +{ + zval *read = NULL, *write = NULL; + fd_set R, W; + int nfds; + long timeout; + struct timeval tv; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aal", &read, &write, &timeout)) { + RETURN_FALSE; + } + + if (timeout) { + tv.tv_sec = timeout / 1000; + tv.tv_usec = timeout % (timeout * 1000); + } else { + tv.tv_sec = 1; + tv.tv_usec = 0; + } + + FD_ZERO(&R); + FD_ZERO(&W); + + nfds = php_ares_extract_fds(read, write, &R, &W); + 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; + } + RETURN_FALSE; +} +/* }}} */ + +/* proto int ares_timeout(resource ares[, int max_timout_ms]) + Get suggested select timeout in ms */ +static PHP_FUNCTION(ares_timeout) +{ + zval *rsrc; + long max_timeout = -1; + struct timeval tv, *tvptr; + php_ares *ares; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + + if ((tvptr = php_ares_timeout(ares, max_timeout, &tv))) { + RETURN_LONG(tvptr->tv_sec * 1000 + tvptr->tv_usec / 1000); + } + RETURN_LONG(0); +} +/* }}} */ + +/* {{{ proto int ares_fds(resource ares, array &read, array &write) + Get file descriptors */ +static PHP_FUNCTION(ares_fds) +{ + zval *rsrc, *read, *write; + fd_set R, W; + php_ares *ares; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzz", &rsrc, &read, &write)) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares); + + FD_ZERO(&R); + FD_ZERO(&W); + + zval_dtor(read); + zval_dtor(write); + array_init(read); + array_init(write); + ares_fds(ares->channel, &R, &W); + RETVAL_LONG(php_ares_publish_fds(&R, &W, read, write)); +} +/* }}} */ + +static ZEND_RSRC_DTOR_FUNC(php_ares_le_dtor) +{ + php_ares *ares = (php_ares *) rsrc->ptr; + + ares_destroy(ares->channel); + zend_llist_destroy(&ares->queries); + php_ares_options_dtor(&ares->options); + efree(ares); +} + +static ZEND_RSRC_DTOR_FUNC(php_ares_query_le_dtor) +{ + php_ares_query *query = (php_ares_query *) rsrc->ptr; + + php_ares_query_dtor(query); + efree(query); +} + +/* {{{ PHP_MINIT_FUNCTION */ +static PHP_MINIT_FUNCTION(ares) +{ +#ifdef HAVE_ARES_LIBRARY_INIT + if (ARES_SUCCESS != ares_library_init(ARES_LIB_INIT_ALL)) { + return FAILURE; + } +#endif +#ifdef HAVE_ARES_VERSION + { + int ares_version_num; + ares_version(&ares_version_num); + + REGISTER_LONG_CONSTANT("ARES_VERSION", ares_version_num, CONST_PERSISTENT|CONST_CS); + } +#endif + + REGISTER_LONG_CONSTANT("ARES_SUCCESS", ARES_SUCCESS, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_ENODATA", ARES_ENODATA, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_EFORMERR", ARES_EFORMERR, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_ESERVFAIL", ARES_ESERVFAIL, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_ENOTFOUND", ARES_ENOTFOUND, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_ENOTIMP", ARES_ENOTIMP, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_EREFUSED", ARES_EREFUSED, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_EBADQUERY", ARES_EBADQUERY, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_EBADNAME", ARES_EBADNAME, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_EBADFAMILY", ARES_EBADFAMILY, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_EBADRESP", ARES_EBADRESP, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_ECONNREFUSED", ARES_ECONNREFUSED, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_ETIMEOUT", ARES_ETIMEOUT, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_EOF", ARES_EOF, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_EFILE", ARES_EFILE, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_ENOMEM", ARES_ENOMEM, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_EDESTRUCTION", ARES_EDESTRUCTION, CONST_PERSISTENT|CONST_CS); +#ifdef ARES_EBADSTR + REGISTER_LONG_CONSTANT("ARES_EBADSTR", ARES_EBADSTR, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_EBADFLAGS + REGISTER_LONG_CONSTANT("ARES_EBADFLAGS", ARES_EBADFLAGS, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_ENONAME + REGISTER_LONG_CONSTANT("ARES_ENONAME", ARES_ENONAME, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_EBADHINTS + REGISTER_LONG_CONSTANT("ARES_EBADHINTS", ARES_EBADHINTS, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_ENOTINITIALIZED + REGISTER_LONG_CONSTANT("ARES_ENOTINITIALIZED", ARES_ENOTINITIALIZED, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_ELOADIPHLPAPI + REGISTER_LONG_CONSTANT("ARES_ELOADIPHLPAPI", ARES_ELOADIPHLPAPI, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_EADDRGETNETWORKPARAMS + REGISTER_LONG_CONSTANT("ARES_EADDRGETNETWORKPARAMS", ARES_EADDRGETNETWORKPARAMS, CONST_PERSISTENT|CONST_CS); +#endif + +/* More error codes */ +#define ARES_ECANCELLED 24 /* introduced in 1.7.0 */ + + REGISTER_LONG_CONSTANT("ARES_FLAG_USEVC", ARES_FLAG_USEVC, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_FLAG_PRIMARY", ARES_FLAG_PRIMARY, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_FLAG_IGNTC", ARES_FLAG_IGNTC, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_FLAG_NORECURSE", ARES_FLAG_NORECURSE, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_FLAG_STAYOPEN", ARES_FLAG_STAYOPEN, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_FLAG_NOSEARCH", ARES_FLAG_NOSEARCH, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_FLAG_NOALIASES", ARES_FLAG_NOALIASES, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_FLAG_NOCHECKRESP", ARES_FLAG_NOCHECKRESP, CONST_PERSISTENT|CONST_CS); + + /* + * Address Family Constants + */ + REGISTER_LONG_CONSTANT("ARES_AF_INET", AF_INET, CONST_PERSISTENT|CONST_CS); + REGISTER_LONG_CONSTANT("ARES_AF_INET6", AF_INET6, CONST_PERSISTENT|CONST_CS); + + /* + * Name Info constants + */ +#ifdef ARES_NI_NOFQDN + REGISTER_LONG_CONSTANT("ARES_NI_NOFQDN", ARES_NI_NOFQDN, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_NUMERICHOST + REGISTER_LONG_CONSTANT("ARES_NI_NUMERICHOST", ARES_NI_NUMERICHOST, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_NAMEREQD + REGISTER_LONG_CONSTANT("ARES_NI_NAMEREQD", ARES_NI_NAMEREQD, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_NUMERICSERV + REGISTER_LONG_CONSTANT("ARES_NI_NUMERICSERV", ARES_NI_NUMERICSERV, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_DGRAM + REGISTER_LONG_CONSTANT("ARES_NI_DGRAM", ARES_NI_DGRAM, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_TCP + REGISTER_LONG_CONSTANT("ARES_NI_TCP", ARES_NI_TCP, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_UDP + REGISTER_LONG_CONSTANT("ARES_NI_UDP", ARES_NI_UDP, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_SCTP + REGISTER_LONG_CONSTANT("ARES_NI_SCTP", ARES_NI_SCTP, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_DCCP + REGISTER_LONG_CONSTANT("ARES_NI_DCCP", ARES_NI_DCCP, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_NUMERICSCOPE + REGISTER_LONG_CONSTANT("ARES_NI_NUMERICSCOPE", ARES_NI_NUMERICSCOPE, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_LOOKUPHOST + REGISTER_LONG_CONSTANT("ARES_NI_LOOKUPHOST", ARES_NI_LOOKUPHOST, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_LOOKUPSERVICE + REGISTER_LONG_CONSTANT("ARES_NI_LOOKUPSERVICE", ARES_NI_LOOKUPSERVICE, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_IDN + REGISTER_LONG_CONSTANT("ARES_NI_IDN", ARES_NI_IDN, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_IDN_ALLOW_UNASSIGNED + REGISTER_LONG_CONSTANT("ARES_NI_IDN_ALLOW_UNASSIGNED", ARES_NI_IDN_ALLOW_UNASSIGNED, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_NI_IDN_USE_STD + REGISTER_LONG_CONSTANT("ARES_NI_IDN_USE_STD", ARES_NI_IDN_USE_STD, CONST_PERSISTENT|CONST_CS); +#endif + + /* + * Address Info constants + */ +#ifdef ARES_AI_CANONNAME + REGISTER_LONG_CONSTANT("ARES_AI_CANONNAME", ARES_AI_CANONNAME, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_AI_NUMERICHOST + REGISTER_LONG_CONSTANT("ARES_AI_NUMERICHOST", ARES_AI_NUMERICHOST, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_AI_PASSIVE + REGISTER_LONG_CONSTANT("ARES_AI_PASSIVE", ARES_AI_PASSIVE, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_AI_NUMERICSERV + REGISTER_LONG_CONSTANT("ARES_AI_NUMERICSERV", ARES_AI_NUMERICSERV, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_AI_V + REGISTER_LONG_CONSTANT("ARES_AI_V", ARES_AI_V, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_AI_ALL + REGISTER_LONG_CONSTANT("ARES_AI_ALL", ARES_AI_ALL, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_AI_ADDRCONFIG + REGISTER_LONG_CONSTANT("ARES_AI_ADDRCONFIG", ARES_AI_ADDRCONFIG, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_AI_IDN + REGISTER_LONG_CONSTANT("ARES_AI_IDN", ARES_AI_IDN, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_AI_IDN_ALLOW_UNASSIGNED + REGISTER_LONG_CONSTANT("ARES_AI_IDN_ALLOW_UNASSIGNED", ARES_AI_IDN_ALLOW_UNASSIGNED, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_AI_IDN_USE_STD + REGISTER_LONG_CONSTANT("ARES_AI_IDN_USE_STD", ARES_AI_IDN_USE_STD, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_AI_CANONIDN + REGISTER_LONG_CONSTANT("ARES_AI_CANONIDN", ARES_AI_CANONIDN, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_AI_MASK + REGISTER_LONG_CONSTANT("ARES_AI_MASK", ARES_AI_MASK, CONST_PERSISTENT|CONST_CS); +#endif +#ifdef ARES_GETSOCK_MAXNUM + REGISTER_LONG_CONSTANT("ARES_GETSOCK_MAXNUM", ARES_GETSOCK_MAXNUM, CONST_PERSISTENT|CONST_CS); +#endif + + /* + * ns_t (type) constants (arpa/nameser.h) + */ +#ifdef T_A + /* (1) Host address. */ + REGISTER_LONG_CONSTANT("ARES_T_A", T_A, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_NS + /* (2) Authoritative server. */ + REGISTER_LONG_CONSTANT("ARES_T_NS", T_NS, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_MD + /* (3) Mail destination. */ + REGISTER_LONG_CONSTANT("ARES_T_MD", T_MD, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_MF + /* (4) Mail forwarder. */ + REGISTER_LONG_CONSTANT("ARES_T_MF", T_MF, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_CNAME + /* (5) Canonical name. */ + REGISTER_LONG_CONSTANT("ARES_T_CNAME", T_CNAME, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_SOA + /* (6) Start of authority zone. */ + REGISTER_LONG_CONSTANT("ARES_T_SOA", T_SOA, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_MB + /* (7) Mailbox domain name. */ + REGISTER_LONG_CONSTANT("ARES_T_MB", T_MB, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_MG + /* (8) Mail group member. */ + REGISTER_LONG_CONSTANT("ARES_T_MG", T_MG, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_MR + /* (9) Mail rename name. */ + REGISTER_LONG_CONSTANT("ARES_T_MR", T_MR, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_NULL + /* (10) Null resource record. */ + REGISTER_LONG_CONSTANT("ARES_T_NULL", T_NULL, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_WKS + /* (11) Well known service. */ + REGISTER_LONG_CONSTANT("ARES_T_WKS", T_WKS, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_PTR + /* (12) Domain name pointer. */ + REGISTER_LONG_CONSTANT("ARES_T_PTR", T_PTR, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_HINFO + /* (13) Host information. */ + REGISTER_LONG_CONSTANT("ARES_T_HINFO", T_HINFO, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_MINFO + /* (14) Mailbox information. */ + REGISTER_LONG_CONSTANT("ARES_T_MINFO", T_MINFO, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_MX + /* (15) Mail routing information. */ + REGISTER_LONG_CONSTANT("ARES_T_MX", T_MX, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_TXT + /* (16) Text strings. */ + REGISTER_LONG_CONSTANT("ARES_T_TXT", T_TXT, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_RP + /* (17) Responsible person. */ + REGISTER_LONG_CONSTANT("ARES_T_RP", T_RP, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_AFSDB + /* (18) AFS cell database. */ + REGISTER_LONG_CONSTANT("ARES_T_AFSDB", T_AFSDB, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_X25 + /* (19) X_25 calling address. */ + REGISTER_LONG_CONSTANT("ARES_T_X25", T_X25, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_ISDN + /* (20) ISDN calling address. */ + REGISTER_LONG_CONSTANT("ARES_T_ISDN", T_ISDN, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_RT + /* (21) Router. */ + REGISTER_LONG_CONSTANT("ARES_T_RT", T_RT, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_NSAP + /* (22) NSAP address. */ + REGISTER_LONG_CONSTANT("ARES_T_NSAP", T_NSAP, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_NSAP_PTR + /* (23) Reverse NSAP lookup (deprecated). */ + REGISTER_LONG_CONSTANT("ARES_T_NSAP_PTR", T_NSAP_PTR, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_SIG + /* (24) Security signature. */ + REGISTER_LONG_CONSTANT("ARES_T_SIG", T_SIG, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_KEY + /* (25) Security key. */ + REGISTER_LONG_CONSTANT("ARES_T_KEY", T_KEY, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_PX + /* (26) X.400 mail mapping. */ + REGISTER_LONG_CONSTANT("ARES_T_PX", T_PX, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_GPOS + /* (27) Geographical position (withdrawn). */ + REGISTER_LONG_CONSTANT("ARES_T_GPOS", T_GPOS, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_AAAA + /* (28) Ip6 Address. */ + REGISTER_LONG_CONSTANT("ARES_T_AAAA", T_AAAA, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_LOC + /* (29) Location Information. */ + REGISTER_LONG_CONSTANT("ARES_T_LOC", T_LOC, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_NXT + /* (30) Next domain (security). */ + REGISTER_LONG_CONSTANT("ARES_T_NXT", T_NXT, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_EID + /* (31) Endpoint identifier. */ + REGISTER_LONG_CONSTANT("ARES_T_EID", T_EID, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_NIMLOC + /* (32) Nimrod Locator. */ + REGISTER_LONG_CONSTANT("ARES_T_NIMLOC", T_NIMLOC, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_SRV + /* (33) Server Selection. */ + REGISTER_LONG_CONSTANT("ARES_T_SRV", T_SRV, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_ATMA + /* (34) ATM Address */ + REGISTER_LONG_CONSTANT("ARES_T_ATMA", T_ATMA, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_NAPTR + /* (35) Naming Authority Pointer */ + REGISTER_LONG_CONSTANT("ARES_T_NAPTR", T_NAPTR, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_KX + /* (36) Key Exchange */ + REGISTER_LONG_CONSTANT("ARES_T_KX", T_KX, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_CERT + /* (37) Certification record */ + REGISTER_LONG_CONSTANT("ARES_T_CERT", T_CERT, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_A6 + /* (38) IPv6 address (deprecates AAAA) */ + REGISTER_LONG_CONSTANT("ARES_T_A6", T_A6, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_DNAME + /* (39) Non-terminal DNAME (for IPv6) */ + REGISTER_LONG_CONSTANT("ARES_T_DNAME", T_DNAME, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_SINK + /* (40) Kitchen sink (experimentatl) */ + REGISTER_LONG_CONSTANT("ARES_T_SINK", T_SINK, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_OPT + /* (41) EDNS0 option (meta-RR) */ + REGISTER_LONG_CONSTANT("ARES_T_OPT", T_OPT, CONST_CS|CONST_PERSISTENT); +#ifdef T_TSIG + /* (250) Transaction signature. */ + REGISTER_LONG_CONSTANT("ARES_T_TSIG", T_TSIG, CONST_CS|CONST_PERSISTENT); +#endif T_IXFR + /* (251) Incremental zone transfer. */ + REGISTER_LONG_CONSTANT("ARES_T_IXFR", T_IXFR, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_AXFR + /* (252) Transfer zone of authority. */ + REGISTER_LONG_CONSTANT("ARES_T_AXFR", T_AXFR, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_MAILB + /* (253) Transfer mailbox records. */ + REGISTER_LONG_CONSTANT("ARES_T_MAILB", T_MAILB, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_MAILA + /* (254) Transfer mail agent records. */ + REGISTER_LONG_CONSTANT("ARES_T_MAILA", T_MAILA, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef T_ANY + /* (255) Wildcard match. */ + REGISTER_LONG_CONSTANT("ARES_T_ANY", T_ANY, CONST_CS|CONST_PERSISTENT); +#endif + + /* + * ns_c (dnsclass) constants (arpa/nameser.h) + */ + +#ifdef C_IN + /* (1) Internet. */ + REGISTER_LONG_CONSTANT("ARES_C_IN", C_IN, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef C_2 + /* (2) unallocated/unsupported. */ + REGISTER_LONG_CONSTANT("ARES_C_2", C_2, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef C_CHAOS + /* (3) MIT Chaos-net. */ + REGISTER_LONG_CONSTANT("ARES_C_CHAOS", C_CHAOS, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef C_HS + /* (4) MIT Hesiod. */ + REGISTER_LONG_CONSTANT("ARES_C_HS", C_HS, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef C_NONE + /* (254) for prereq. sections in update requests */ + REGISTER_LONG_CONSTANT("ARES_C_NONE", C_NONE, CONST_CS|CONST_PERSISTENT); +#endif +#ifdef C_ANY + /* (255) Wildcard match. */ + REGISTER_LONG_CONSTANT("ARES_C_ANY", C_ANY, CONST_CS|CONST_PERSISTENT); +#endif + + le_ares = zend_register_list_destructors_ex(php_ares_le_dtor, NULL, PHP_ARES_LE_NAME, module_number); + le_ares_query = zend_register_list_destructors_ex(php_ares_query_le_dtor, NULL, PHP_ARES_QUERY_LE_NAME, module_number); + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MSHUTDOWN_FUNCTION */ +static PHP_MSHUTDOWN_FUNCTION(ares) +{ +#ifdef HAVE_ARES_LIBRARY_CLEANUP + ares_library_cleanup(); +#endif + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION */ +static PHP_MINFO_FUNCTION(ares) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "AsyncResolver support", "enabled"); + php_info_print_table_row(2, "Version", PHP_ARES_VERSION); + php_info_print_table_end(); + + php_info_print_table_start(); + php_info_print_table_header(3, "Used Library", "compiled", "linked"); + php_info_print_table_row(3, + PHP_ARES_LIBNAME, +#ifdef ARES_VERSION_STR + ARES_VERSION_STR, +#else + "unkown", +#endif +#ifdef HAVE_ARES_VERSION + ares_version(NULL) +#else + "unkown" +#endif + ); + php_info_print_table_end(); +} +/* }}} */ + +#ifdef ZEND_ENGINE_2 +ZEND_BEGIN_ARG_INFO(ai_ares_select, 0) + ZEND_ARG_PASS_INFO(1) + ZEND_ARG_PASS_INFO(1) + ZEND_ARG_PASS_INFO(0) +ZEND_END_ARG_INFO(); + +ZEND_BEGIN_ARG_INFO(ai_ares_result, 0) + ZEND_ARG_PASS_INFO(0) + ZEND_ARG_PASS_INFO(1) + ZEND_ARG_PASS_INFO(1) +ZEND_END_ARG_INFO(); + +ZEND_BEGIN_ARG_INFO(ai_ares_fds, 0) + ZEND_ARG_PASS_INFO(0) + ZEND_ARG_PASS_INFO(1) + ZEND_ARG_PASS_INFO(1) +ZEND_END_ARG_INFO(); +#else +static unsigned char ai_ares_select[] = {3, BYREF_FORCE, BYREF_FORCE, BYREF_NONE}; +static unsigned char ai_ares_result[] = {4, BYREF_NONE, BYREF_FORCE, BYREF_FORCE}; +static unsigned char ai_ares_fds[] = {4, BYREF_NONE, BYREF_FORCE, BYREF_FORCE}; +#endif + +/* {{{ ares_functions[] */ +zend_function_entry ares_functions[] = { +#ifdef HAVE_ARES_VERSION + PHP_FE(ares_version, NULL) +#endif + PHP_FE(ares_init, NULL) + PHP_FE(ares_destroy, NULL) + PHP_FE(ares_strerror, NULL) +#ifdef HAVE_ARES_CANCEL + PHP_FE(ares_cancel, NULL) +#endif + PHP_FE(ares_search, NULL) + PHP_FE(ares_query, NULL) + PHP_FE(ares_send, NULL) + PHP_FE(ares_mkquery, NULL) + PHP_FE(ares_gethostbyname, NULL) + PHP_FE(ares_gethostbyaddr, NULL) +#ifdef HAVE_ARES_GETNAMEINFO + PHP_FE(ares_getnameinfo, NULL) +#endif + PHP_FE(ares_result, ai_ares_result) + PHP_FE(ares_packet, NULL) + PHP_FE(ares_process_all, NULL) + PHP_FE(ares_process_once, NULL) + PHP_FE(ares_process, NULL) + PHP_FE(ares_select, ai_ares_select) + PHP_FE(ares_fds, ai_ares_fds) + PHP_FE(ares_timeout, NULL) + {NULL, NULL, NULL} +}; +/* }}} */ + +/* {{{ ares_module_entry */ +zend_module_entry ares_module_entry = { + STANDARD_MODULE_HEADER, + "ares", + ares_functions, + PHP_MINIT(ares), + PHP_MSHUTDOWN(ares), + NULL, + NULL, + PHP_MINFO(ares), + PHP_ARES_VERSION, + STANDARD_MODULE_PROPERTIES +}; +/* }}} */ + +#ifdef COMPILE_DL_ARES +ZEND_GET_MODULE(ares) +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/php_ares.h b/php_ares.h index 5643c58..8ecd787 100644 --- a/php_ares.h +++ b/php_ares.h @@ -18,7 +18,7 @@ extern zend_module_entry ares_module_entry; #define phpext_ares_ptr &ares_module_entry -#define PHP_ARES_VERSION "0.7.0" +#define PHP_ARES_VERSION "0.8.0dev" #ifdef ZTS #include "TSRM.h"