summaryrefslogtreecommitdiff
path: root/src/rexmpp_tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rexmpp_tcp.c')
-rw-r--r--src/rexmpp_tcp.c104
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 &&