diff options
Diffstat (limited to 'src/rexmpp_tcp.c')
-rw-r--r-- | src/rexmpp_tcp.c | 104 |
1 files changed, 58 insertions, 46 deletions
diff --git a/src/rexmpp_tcp.c b/src/rexmpp_tcp.c index e57cfb8..ac32e57 100644 --- a/src/rexmpp_tcp.c +++ b/src/rexmpp_tcp.c @@ -6,7 +6,7 @@ @copyright MIT license. */ -#include <ares.h> +#include <unbound.h> #include <netdb.h> #include <arpa/nameser.h> #include <sys/socket.h> @@ -24,15 +24,13 @@ void rexmpp_dns_aaaa_cb (void *ptr, int status, - int timeouts, - unsigned char *abuf, - int alen) + struct ub_result *result) { rexmpp_tcp_conn_t *conn = ptr; conn->resolver_status_v6 = status; - if (status == ARES_SUCCESS) { + conn->resolved_v6 = result; + if (status == 0 && ! result->bogus && result->havedata) { conn->resolution_v6 = REXMPP_CONN_RESOLUTION_SUCCESS; - ares_parse_aaaa_reply(abuf, alen, &(conn->addr_v6), NULL, NULL); conn->addr_cur_v6 = -1; } else { conn->resolution_v6 = REXMPP_CONN_RESOLUTION_FAILURE; @@ -41,15 +39,13 @@ void rexmpp_dns_aaaa_cb (void *ptr, void rexmpp_dns_a_cb (void *ptr, int status, - int timeouts, - unsigned char *abuf, - int alen) + struct ub_result *result) { rexmpp_tcp_conn_t *conn = ptr; conn->resolver_status_v4 = status; - if (status == ARES_SUCCESS) { + conn->resolved_v4 = result; + if (status == 0 && ! result->bogus && result->havedata) { conn->resolution_v4 = REXMPP_CONN_RESOLUTION_SUCCESS; - ares_parse_a_reply(abuf, alen, &(conn->addr_v4), NULL, NULL); conn->addr_cur_v4 = -1; if (conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) { /* Wait for 50 ms for IPv6. */ @@ -74,22 +70,29 @@ void rexmpp_tcp_cleanup (rexmpp_tcp_conn_t *conn) { } } if (conn->resolution_v4 != REXMPP_CONN_RESOLUTION_INACTIVE) { - ares_destroy(conn->resolver_channel); conn->resolution_v4 = REXMPP_CONN_RESOLUTION_INACTIVE; conn->resolution_v6 = REXMPP_CONN_RESOLUTION_INACTIVE; } - if (conn->addr_v4 != NULL) { - ares_free_hostent(conn->addr_v4); - conn->addr_v4 = NULL; + if (conn->resolved_v4 != NULL) { + ub_resolve_free(conn->resolved_v4); + conn->resolved_v4 = NULL; } - if (conn->addr_v6 != NULL) { - ares_free_hostent(conn->addr_v6); - conn->addr_v6 = NULL; + if (conn->resolved_v6 != NULL) { + ub_resolve_free(conn->resolved_v6); + conn->resolved_v6 = NULL; } } rexmpp_tcp_conn_error_t rexmpp_tcp_connected (rexmpp_tcp_conn_t *conn, int fd) { + struct sockaddr sa; + socklen_t sa_len = sizeof(sa); + getsockname(fd, &sa, &sa_len); + if (sa.sa_family == AF_INET) { + conn->dns_secure = conn->resolved_v4->secure; + } else { + conn->dns_secure = conn->resolved_v6->secure; + } conn->fd = fd; rexmpp_tcp_cleanup(conn); return REXMPP_CONN_DONE; @@ -97,6 +100,7 @@ rexmpp_tcp_connected (rexmpp_tcp_conn_t *conn, int fd) { rexmpp_tcp_conn_error_t rexmpp_tcp_conn_init (rexmpp_tcp_conn_t *conn, + struct ub_ctx *resolver_ctx, const char *host, uint16_t port) { @@ -106,9 +110,10 @@ rexmpp_tcp_conn_init (rexmpp_tcp_conn_t *conn, } conn->connection_attempts = 0; conn->port = port; - conn->addr_v4 = NULL; - conn->addr_v6 = NULL; + conn->resolved_v4 = NULL; + conn->resolved_v6 = NULL; conn->fd = -1; + conn->dns_secure = 0; conn->next_connection_time.tv_sec = 0; conn->next_connection_time.tv_usec = 0; @@ -160,15 +165,12 @@ rexmpp_tcp_conn_init (rexmpp_tcp_conn_t *conn, } conn->resolution_v4 = REXMPP_CONN_RESOLUTION_WAITING; conn->resolution_v6 = REXMPP_CONN_RESOLUTION_WAITING; - conn->resolver_error = ares_init(&(conn->resolver_channel)); - if (conn->resolver_error != ARES_SUCCESS) { - return REXMPP_CONN_RESOLVER_ERROR; - } + conn->resolver_ctx = resolver_ctx; - ares_query(conn->resolver_channel, host, - ns_c_in, ns_t_aaaa, rexmpp_dns_aaaa_cb, conn); - ares_query(conn->resolver_channel, host, - ns_c_in, ns_t_a, rexmpp_dns_a_cb, conn); + ub_resolve_async(conn->resolver_ctx, host, 28, 1, + conn, rexmpp_dns_aaaa_cb, NULL); + ub_resolve_async(conn->resolver_ctx, host, 1, 1, + conn, rexmpp_dns_a_cb, NULL); return REXMPP_CONN_IN_PROGRESS; } @@ -180,14 +182,14 @@ int rexmpp_tcp_conn_finish (rexmpp_tcp_conn_t *conn) { int rexmpp_tcp_conn_ipv4_available(rexmpp_tcp_conn_t *conn) { return (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_SUCCESS && - conn->addr_v4 != NULL && - conn->addr_v4->h_addr_list[conn->addr_cur_v4 + 1] != NULL); + conn->resolved_v4 != NULL && + conn->resolved_v4->data[conn->addr_cur_v4 + 1] != NULL); } int rexmpp_tcp_conn_ipv6_available(rexmpp_tcp_conn_t *conn) { return (conn->resolution_v6 == REXMPP_CONN_RESOLUTION_SUCCESS && - conn->addr_v6 != NULL && - conn->addr_v6->h_addr_list[conn->addr_cur_v6 + 1] != NULL); + conn->resolved_v6 != NULL && + conn->resolved_v6->data[conn->addr_cur_v6 + 1] != NULL); } rexmpp_tcp_conn_error_t @@ -219,7 +221,9 @@ rexmpp_tcp_conn_proceed (rexmpp_tcp_conn_t *conn, /* Name resolution. */ if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_WAITING || conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) { - ares_process(conn->resolver_channel, read_fds, write_fds); + if (ub_poll(conn->resolver_ctx)) { + ub_process(conn->resolver_ctx); + } } if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_FAILURE && @@ -255,25 +259,34 @@ rexmpp_tcp_conn_proceed (rexmpp_tcp_conn_t *conn, struct sockaddr *addr; socklen_t addrlen; int domain; + int len; if (use_ipv6) { conn->addr_cur_v6++; + len = sizeof(addr_v6.sin6_addr); + if (len > conn->resolved_v6->len[conn->addr_cur_v6]) { + len = conn->resolved_v6->len[conn->addr_cur_v6]; + } memcpy(&addr_v6.sin6_addr, - conn->addr_v6->h_addr_list[conn->addr_cur_v6], - conn->addr_v6->h_length); - addr_v6.sin6_family = conn->addr_v6->h_addrtype; + conn->resolved_v6->data[conn->addr_cur_v6], + len); + addr_v6.sin6_family = AF_INET6; addr_v6.sin6_port = htons(conn->port); - domain = conn->addr_v6->h_addrtype; + domain = AF_INET6; addr = (struct sockaddr*)&addr_v6; addrlen = sizeof(addr_v6); } else { conn->addr_cur_v4++; + len = sizeof(addr_v4.sin_addr); + if (len > conn->resolved_v4->len[conn->addr_cur_v4]) { + len = conn->resolved_v4->len[conn->addr_cur_v4]; + } memcpy(&addr_v4.sin_addr, - conn->addr_v4->h_addr_list[conn->addr_cur_v4], - conn->addr_v4->h_length); - addr_v4.sin_family = conn->addr_v4->h_addrtype; + conn->resolved_v4->data[conn->addr_cur_v4], + len); + addr_v4.sin_family = AF_INET; addr_v4.sin_port = htons(conn->port); - domain = conn->addr_v4->h_addrtype; + domain = AF_INET; addr = (struct sockaddr*)&addr_v4; addrlen = sizeof(addr_v4); } @@ -337,7 +350,10 @@ int rexmpp_tcp_conn_fds (rexmpp_tcp_conn_t *conn, int max_fd = 0, i; if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_WAITING || conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) { - max_fd = ares_fds(conn->resolver_channel, read_fds, write_fds); + max_fd = ub_fd(conn->resolver_ctx) + 1; + if (max_fd != 0) { + FD_SET(max_fd - 1, read_fds); + } } for (i = 0; i < REXMPP_TCP_MAX_CONNECTION_ATTEMPTS; i++) { if (conn->sockets[i] != -1) { @@ -356,10 +372,6 @@ struct timeval *rexmpp_tcp_conn_timeout (rexmpp_tcp_conn_t *conn, { struct timeval now; struct timeval *ret = max_tv; - if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_WAITING || - conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) { - ret = ares_timeout(conn->resolver_channel, max_tv, tv); - } if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_SUCCESS || conn->resolution_v6 == REXMPP_CONN_RESOLUTION_SUCCESS || (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_INACTIVE && |