diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/rexmpp.c | 118 | ||||
-rw-r--r-- | src/rexmpp.h | 12 | ||||
-rw-r--r-- | src/rexmpp_dns.c | 291 | ||||
-rw-r--r-- | src/rexmpp_dns.h | 48 | ||||
-rw-r--r-- | src/rexmpp_tcp.c | 62 | ||||
-rw-r--r-- | src/rexmpp_tcp.h | 31 |
7 files changed, 420 insertions, 144 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index deb3ac6..51a5da7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -32,7 +32,7 @@ include_HEADERS = config.h rexmpp_roster.h rexmpp_tcp.h rexmpp_socks.h rexmpp.h rexmpp_pubsub.h librexmpp_la_CFLAGS = $(AM_CFLAGS) $(LIBXML_CFLAGS) \ $(GNUTLS_CFLAGS) $(LIBDANE_CFLAGS) $(OPENSSL_CFLAGS) \ - $(GSASL_CFLAGS) $(UNBOUND_CFLAGS) $(GPGME_CFLAGS) + $(GSASL_CFLAGS) $(UNBOUND_CFLAGS) $(GPGME_CFLAGS) \ $(ICU_I18N_CFLAGS) $(NETTLE_CFLAGS) librexmpp_la_LIBADD = $(LIBXML_LIBS) \ $(GNUTLS_LIBS) $(LIBDANE_LIBS) $(OPENSSL_LIBS) \ diff --git a/src/rexmpp.c b/src/rexmpp.c index 8998ea9..b35e40a 100644 --- a/src/rexmpp.c +++ b/src/rexmpp.c @@ -400,7 +400,6 @@ rexmpp_err_t rexmpp_init (rexmpp_t *s, s->tls_policy = REXMPP_TLS_REQUIRE; s->send_buffer = NULL; s->send_queue = NULL; - s->resolver_ctx = NULL; s->server_srv = NULL; s->server_srv_cur = -1; s->server_srv_tls = NULL; @@ -458,30 +457,13 @@ rexmpp_err_t rexmpp_init (rexmpp_t *s, return REXMPP_E_XML; } - s->resolver_ctx = ub_ctx_create(); - if (s->resolver_ctx == NULL) { - rexmpp_log(s, LOG_CRIT, "Failed to create resolver context"); + if (rexmpp_dns_ctx_init(s)) { xmlFreeParserCtxt(s->xml_parser); return REXMPP_E_DNS; } - err = ub_ctx_resolvconf(s->resolver_ctx, NULL); - if (err != 0) { - rexmpp_log(s, LOG_WARNING, "Failed to read resolv.conf: %s", - ub_strerror(err)); - } - err = ub_ctx_hosts(s->resolver_ctx, NULL); - if (err != 0) { - rexmpp_log(s, LOG_WARNING, "Failed to read hosts file: %s", - ub_strerror(err)); - } - /* todo: better to make this path configurable, not to hardcode it */ - err = ub_ctx_add_ta_file(s->resolver_ctx, DNSSEC_TRUST_ANCHOR_FILE); - if (err != 0) { - rexmpp_log(s, LOG_WARNING, "Failed to set root key file for DNSSEC: %s", - ub_strerror(err)); - } if (rexmpp_tls_init(s)) { + rexmpp_dns_ctx_deinit(s); xmlFreeParserCtxt(s->xml_parser); return REXMPP_E_TLS; } @@ -491,6 +473,7 @@ rexmpp_err_t rexmpp_init (rexmpp_t *s, rexmpp_log(s, LOG_CRIT, "gsasl initialisation error: %s", gsasl_strerror(err)); rexmpp_tls_deinit(s); + rexmpp_dns_ctx_deinit(s); xmlFreeParserCtxt(s->xml_parser); return REXMPP_E_SASL; } @@ -505,6 +488,7 @@ rexmpp_err_t rexmpp_init (rexmpp_t *s, gpgme_strerror(err)); gsasl_done(s->sasl_ctx); rexmpp_tls_deinit(s); + rexmpp_dns_ctx_deinit(s); xmlFreeParserCtxt(s->xml_parser); return REXMPP_E_PGP; } @@ -559,12 +543,12 @@ void rexmpp_cleanup (rexmpp_t *s) { s->input_queue_last = NULL; } if (s->server_srv != NULL) { - ub_resolve_free(s->server_srv); + rexmpp_dns_result_free(s->server_srv); s->server_srv = NULL; s->server_srv_cur = -1; } if (s->server_srv_tls != NULL) { - ub_resolve_free(s->server_srv_tls); + rexmpp_dns_result_free(s->server_srv_tls); s->server_srv_tls = NULL; s->server_srv_tls_cur = -1; } @@ -580,10 +564,7 @@ void rexmpp_done (rexmpp_t *s) { #endif gsasl_done(s->sasl_ctx); rexmpp_tls_deinit(s); - if (s->resolver_ctx != NULL) { - ub_ctx_delete(s->resolver_ctx); - s->resolver_ctx = NULL; - } + rexmpp_dns_ctx_deinit(s); xmlFreeParserCtxt(s->xml_parser); if (s->stream_id != NULL) { free(s->stream_id); @@ -1148,8 +1129,8 @@ rexmpp_err_t rexmpp_start_connecting (rexmpp_t *s) { s->server_host, s->server_port); return rexmpp_process_conn_err(s, - rexmpp_tcp_conn_init(&s->server_connection, - s->resolver_ctx, + rexmpp_tcp_conn_init(s, + &s->server_connection, s->server_host, s->server_port)); } else { @@ -1157,15 +1138,15 @@ rexmpp_err_t rexmpp_start_connecting (rexmpp_t *s) { s->server_host, s->server_port, s->socks_host, s->socks_port); return rexmpp_process_conn_err(s, - rexmpp_tcp_conn_init(&s->server_connection, - s->resolver_ctx, + rexmpp_tcp_conn_init(s, + &s->server_connection, s->socks_host, s->socks_port)); } } rexmpp_err_t rexmpp_try_next_host (rexmpp_t *s) { - struct ub_result *cur_result; + rexmpp_dns_result_t *cur_result; int cur_number; /* todo: check priorities and weights */ s->tls_state = REXMPP_TLS_INACTIVE; @@ -1301,34 +1282,22 @@ rexmpp_process_conn_err (rexmpp_t *s, return REXMPP_E_AGAIN; } -void rexmpp_srv_cb (void *s_ptr, - int err, - struct ub_result *result) +void rexmpp_srv_cb (rexmpp_t *s, + void *ptr, + rexmpp_dns_result_t *result) { - rexmpp_t *s = s_ptr; - if (err == 0) { - if (result->bogus) { - rexmpp_log(s, LOG_WARNING, - "Received a bogus SRV resolution result for %s", - result->qname); - } else if (result->havedata) { - rexmpp_log(s, - result->secure ? LOG_DEBUG : LOG_WARNING, - "Resolved %s SRV record (%s)", - result->qname, result->secure ? "secure" : "not secure"); - if (strncmp("_xmpp-", result->qname, 6) == 0) { - s->server_srv = result; - } else { - s->server_srv_tls = result; - } + (void)ptr; + if (result != NULL) { + rexmpp_log(s, + result->secure ? LOG_DEBUG : LOG_WARNING, + "Resolved %s SRV record (%s)", + result->qname, result->secure ? "secure" : "not secure"); + if (strncmp("_xmpp-", result->qname, 6) == 0) { + s->server_srv = result; } else { - rexmpp_log(s, LOG_DEBUG, "No data in the %s SRV result", result->qname); + s->server_srv_tls = result; } - } else { - rexmpp_log(s, LOG_WARNING, "Failed to query %s SRV records: %s", - result->qname, ub_strerror(err)); } - if (s->resolver_state == REXMPP_RESOLVER_SRV) { s->resolver_state = REXMPP_RESOLVER_SRV_2; } else if (s->resolver_state == REXMPP_RESOLVER_SRV_2) { @@ -2257,24 +2226,15 @@ rexmpp_err_t rexmpp_run (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) { if (srv_query == NULL) { return REXMPP_E_MALLOC; } + s->resolver_state = REXMPP_RESOLVER_SRV; snprintf(srv_query, srv_query_buf_len, "_xmpps-client._tcp.%s.", s->initial_jid.domain); - int err; - err = ub_resolve_async(s->resolver_ctx, srv_query, 33, 1, - s, rexmpp_srv_cb, NULL); - if (err) { - rexmpp_log(s, LOG_ERR, "Failed to query %s SRV record: %s", - srv_query, ub_strerror(err)); - } + rexmpp_dns_resolve(s, srv_query, 33, 1, + NULL, rexmpp_srv_cb); snprintf(srv_query, srv_query_buf_len, "_xmpp-client._tcp.%s.", s->initial_jid.domain); - err = ub_resolve_async(s->resolver_ctx, srv_query, 33, 1, - s, rexmpp_srv_cb, NULL); - if (err) { - rexmpp_log(s, LOG_ERR, "Failed to query %s SRV record: %s", - srv_query, ub_strerror(err)); - } - s->resolver_state = REXMPP_RESOLVER_SRV; + rexmpp_dns_resolve(s, srv_query, 33, 1, + NULL, rexmpp_srv_cb); free(srv_query); } else { /* A host is configured manually, connect there. */ @@ -2303,13 +2263,8 @@ rexmpp_err_t rexmpp_run (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) { rexmpp_srv_cb. */ if (s->resolver_state != REXMPP_RESOLVER_NONE && s->resolver_state != REXMPP_RESOLVER_READY) { - if (ub_poll(s->resolver_ctx)) { - int err = ub_process(s->resolver_ctx); - if (err != 0) { - rexmpp_log(s, LOG_ERR, "DNS query processing error: %s", - ub_strerror(err)); - return REXMPP_E_DNS; - } + if (rexmpp_dns_process(s, read_fds, write_fds)) { + return REXMPP_E_DNS; } } @@ -2332,7 +2287,7 @@ rexmpp_err_t rexmpp_run (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) { if (s->tcp_state == REXMPP_TCP_CONNECTING) { rexmpp_err_t err = rexmpp_process_conn_err(s, - rexmpp_tcp_conn_proceed(&s->server_connection, + rexmpp_tcp_conn_proceed(s, &s->server_connection, read_fds, write_fds)); if (err > REXMPP_E_AGAIN) { return err; @@ -2449,14 +2404,11 @@ int rexmpp_fds(rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) { if (s->resolver_state != REXMPP_RESOLVER_NONE && s->resolver_state != REXMPP_RESOLVER_READY) { - max_fd = ub_fd(s->resolver_ctx) + 1; - if (max_fd != 0) { - FD_SET(max_fd - 1, read_fds); - } + max_fd = rexmpp_dns_fds(s, read_fds, write_fds); } if (s->tcp_state == REXMPP_TCP_CONNECTING) { - conn_fd = rexmpp_tcp_conn_fds(&s->server_connection, read_fds, write_fds); + conn_fd = rexmpp_tcp_conn_fds(s, &s->server_connection, read_fds, write_fds); if (conn_fd > max_fd) { max_fd = conn_fd; } @@ -2503,7 +2455,7 @@ struct timeval *rexmpp_timeout (rexmpp_t *s, s->resolver_state != REXMPP_RESOLVER_READY) { } else if (s->tcp_state == REXMPP_TCP_CONNECTING) { - ret = rexmpp_tcp_conn_timeout(&s->server_connection, max_tv, tv); + ret = rexmpp_tcp_conn_timeout(s, &s->server_connection, max_tv, tv); } struct timeval now; gettimeofday(&now, NULL); diff --git a/src/rexmpp.h b/src/rexmpp.h index a7b376a..d8d5e86 100644 --- a/src/rexmpp.h +++ b/src/rexmpp.h @@ -13,7 +13,6 @@ #include "config.h" -#include <unbound.h> #include <gsasl.h> #include <libxml/tree.h> #ifdef HAVE_GPGME @@ -311,10 +310,15 @@ struct rexmpp time_t last_network_activity; /* DNS-related structures. */ - struct ub_ctx *resolver_ctx; - struct ub_result *server_srv; + /* struct ub_ctx *resolver_ctx; */ + /* struct ub_result *server_srv; */ + /* int server_srv_cur; */ + /* struct ub_result *server_srv_tls; */ + /* int server_srv_tls_cur; */ + rexmpp_dns_ctx_t resolver; + rexmpp_dns_result_t *server_srv; int server_srv_cur; - struct ub_result *server_srv_tls; + rexmpp_dns_result_t *server_srv_tls; int server_srv_tls_cur; struct rexmpp_dns_srv server_active_srv; diff --git a/src/rexmpp_dns.c b/src/rexmpp_dns.c index 6a8e743..5b3fd9e 100644 --- a/src/rexmpp_dns.c +++ b/src/rexmpp_dns.c @@ -6,31 +6,298 @@ @copyright MIT license. */ -#include "rexmpp_dns.h" #include <memory.h> +#include <syslog.h> + +#include "config.h" + +#if defined(USE_UNBOUND) +#include <unbound.h> +#else +#include <netdb.h> +#endif + +#include "rexmpp.h" +#include "rexmpp_dns.h" + + +struct rexmpp_dns_query_cb_data { + rexmpp_t *s; + dns_query_cb_t cb; + void *ptr; +}; + + /* https://tools.ietf.org/html/rfc1035#section-3.1 */ + +int rexmpp_dns_parse_qname (char *in, int in_len, char *out, int out_len) { + int i = 0; + while (i < in_len && in[i]) { + if (i + in[i] < in_len && i + in[i] < out_len) { + memcpy(out + i, in + i + 1, in[i]); + i += in[i]; + out[i] = '.'; + i++; + out[i] = '\0'; + } else { + return -1; + } + } + return i; +} + int rexmpp_parse_srv (char *in, int in_len, struct rexmpp_dns_srv *out) { - int i; - char *name; if (in_len < 7 || in_len > 255 + 6) { return -1; } out->priority = in[0] * 0x100 + in[1]; out->weight = in[2] * 0x100 + in[3]; out->port = in[4] * 0x100 + in[5]; - name = in + 6; - i = 0; - while (name[i]) { - if (i + name[i] < 255) { - memcpy(out->target + i, name + i + 1, name[i]); - i += name[i]; - out->target[i] = '.'; - i++; - out->target[i] = '\0'; + if (rexmpp_dns_parse_qname(in + 6, in_len - 6, out->target, 255) < 0) { + return -1; + } + return 0; +} + + +void rexmpp_dns_result_free (rexmpp_dns_result_t *result) { + if (result->data != NULL) { + int i; + for (i = 0; result->data[i] != NULL; i++) { + free(result->data[i]); + } + free(result->data); + result->data = NULL; + } + if (result->len != NULL) { + free(result->len); + result->len = NULL; + } + if (result->qname != NULL) { + free(result->qname); + result->qname = NULL; + } + free(result); +} + + +int rexmpp_dns_ctx_init (rexmpp_t *s) { +#if defined(USE_UNBOUND) + int err; + s->resolver.ctx = ub_ctx_create(); + if (s->resolver.ctx == NULL) { + rexmpp_log(s, LOG_CRIT, "Failed to create resolver context"); + return 1; + } + err = ub_ctx_resolvconf(s->resolver.ctx, NULL); + if (err != 0) { + rexmpp_log(s, LOG_WARNING, "Failed to read resolv.conf: %s", + ub_strerror(err)); + } + err = ub_ctx_hosts(s->resolver.ctx, NULL); + if (err != 0) { + rexmpp_log(s, LOG_WARNING, "Failed to read hosts file: %s", + ub_strerror(err)); + } + err = ub_ctx_add_ta_file(s->resolver.ctx, DNSSEC_TRUST_ANCHOR_FILE); + if (err != 0) { + rexmpp_log(s, LOG_WARNING, "Failed to set root key file for DNSSEC: %s", + ub_strerror(err)); + } + return 0; +#else + (void)s; + return 0; +#endif +} + +void rexmpp_dns_ctx_cleanup (rexmpp_t *s) { +#if defined(USE_UNBOUND) + (void)s; + return; +#else + (void)s; + return; +#endif +} + +void rexmpp_dns_ctx_deinit (rexmpp_t *s) { +#if defined(USE_UNBOUND) + if (s->resolver.ctx != NULL) { + ub_ctx_delete(s->resolver.ctx); + s->resolver.ctx = NULL; + } +#else + (void)s; +#endif +} + +int rexmpp_dns_fds (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) { +#if defined(USE_UNBOUND) + (void)write_fds; + int max_fd = ub_fd(s->resolver.ctx) + 1; + if (max_fd != 0) { + FD_SET(max_fd - 1, read_fds); + } + return max_fd; +#else + (void)s; + (void)read_fds; + (void)write_fds; + return 0; +#endif +} + +struct timeval * rexmpp_dns_timeout (rexmpp_t *s, + struct timeval *max_tv, + struct timeval *tv) +{ +#if defined(USE_UNBOUND) + (void)s; + (void)tv; + return max_tv; +#else + (void)s; + (void)max_tv; + (void)tv; + return max_tv; +#endif +} + +#if defined(USE_UNBOUND) +void rexmpp_dns_cb (void *ptr, + int err, + struct ub_result *result) +{ + struct rexmpp_dns_query_cb_data *d = ptr; + rexmpp_t *s = d->s; + + if (err != 0) { + rexmpp_log(s, LOG_WARNING, "%s DNS query failure: %s", + result->qname, ub_strerror(err)); + ub_resolve_free(result); + d->cb(s, d->ptr, NULL); + return; + } + + if (result->bogus) { + rexmpp_log(s, LOG_WARNING, + "Received a bogus DNS resolution result for %s", + result->qname); + ub_resolve_free(result); + d->cb(s, d->ptr, NULL); + return; + } + + if (! result->havedata) { + rexmpp_log(s, LOG_DEBUG, "No data in the %s query result", result->qname); + ub_resolve_free(result); + d->cb(s, d->ptr, NULL); + return; + } + + int i, size = 0; + while (result->data[size] != NULL) { + size++; + } + rexmpp_dns_result_t *res = malloc(sizeof(rexmpp_dns_result_t)); + res->data = malloc(sizeof(char *) * (size + 1)); + res->len = malloc(sizeof(int) * size); + for (i = 0; i < size; i++) { + res->len[i] = result->len[i]; + res->data[i] = malloc(res->len[i]); + memcpy(res->data[i], result->data[i], res->len[i]); + } + res->data[size] = NULL; + res->secure = result->secure; + res->qname = strdup(result->qname); + ub_resolve_free(result); + d->cb(s, d->ptr, res); + free(d); +} +#endif + + +int rexmpp_dns_resolve (rexmpp_t *s, + const char *query, + int rrtype, + int rrclass, + void* ptr, + dns_query_cb_t callback) +{ +#if defined(USE_UNBOUND) + struct rexmpp_dns_query_cb_data *d = + malloc(sizeof(struct rexmpp_dns_query_cb_data)); + d->s = s; + d->cb = callback; + d->ptr = ptr; + int err = ub_resolve_async(s->resolver.ctx, query, rrtype, rrclass, + d, rexmpp_dns_cb, NULL); + if (err) { + rexmpp_log(s, LOG_ERR, "Failed to query %s: %s", + query, ub_strerror(err)); + return 1; + } +#else + rexmpp_dns_result_t *r = malloc(sizeof(rexmpp_dns_result_t));; + if (rrclass == 1) { + if (rrtype == 1 || rrtype == 28) { + struct hostent *hostinfo = gethostbyname(query); + if (hostinfo == NULL) { + rexmpp_log(s, LOG_ERR, "Failed to lookup %s", query); + callback(s, ptr, NULL); + } else { + r->qname = strdup(query); + r->secure = 0; + int i, size = 0; + while (hostinfo->h_addr_list[size] != NULL) { + size++; + } + r->data = malloc(sizeof(char *) * (size + 1)); + r->len = malloc(sizeof(int) * size); + for (i = 0; i < size; i++) { + r->len[i] = hostinfo->h_length; + r->data[i] = malloc(r->len[i]); + memcpy(r->data[i], hostinfo->h_addr_list[i], hostinfo->h_length); + } + r->data[size] = NULL; + callback(s, ptr, r); + } + } else if (rrtype == 33) { + rexmpp_log(s, LOG_WARNING, "rexmpp is built without SRV lookup support"); + callback(s, ptr, NULL); } else { + rexmpp_log(s, LOG_ERR, "A DNS lookup of unrecognized type is requested"); + callback(s, ptr, NULL); return -1; } + } else { + rexmpp_log(s, LOG_ERR, "A DNS lookup of unrecognized class is requested"); + callback(s, ptr, NULL); + return -1; + } +#endif + return 0; +} + +int rexmpp_dns_process (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) { +#if defined(USE_UNBOUND) + (void)read_fds; + (void)write_fds; + if (ub_poll(s->resolver.ctx)) { + int err = ub_process(s->resolver.ctx); + if (err != 0) { + rexmpp_log(s, LOG_ERR, "DNS query processing error: %s", + ub_strerror(err)); + return 1; + } } return 0; +#else + (void)s; + (void)read_fds; + (void)write_fds; + return 0; +#endif } diff --git a/src/rexmpp_dns.h b/src/rexmpp_dns.h index 9d9f271..3c94e90 100644 --- a/src/rexmpp_dns.h +++ b/src/rexmpp_dns.h @@ -11,6 +11,22 @@ #define REXMPP_DNS_H #include <stdint.h> +#include "config.h" + +#include "rexmpp.h" + +#if defined(USE_UNBOUND) +#include <unbound.h> +struct rexmpp_dns_ctx { + struct ub_ctx *ctx; +}; +#else +struct rexmpp_dns_ctx { + int dummy; +}; +#endif + +typedef struct rexmpp_dns_ctx rexmpp_dns_ctx_t; struct rexmpp_dns_srv { uint16_t priority; @@ -19,6 +35,13 @@ struct rexmpp_dns_srv { char target[256]; }; +struct rexmpp_dns_result { + char **data; + int *len; + char *qname; + int secure; +}; + /** @brief Parses an SRV DNS RR's RDATA. @param[in] in SRV record's RDATA. @@ -29,4 +52,29 @@ struct rexmpp_dns_srv { int rexmpp_parse_srv (char *in, int in_len, struct rexmpp_dns_srv *out); +typedef struct rexmpp_dns_result rexmpp_dns_result_t; + +/* struct rexmpp_dns_result *rexmpp_dns_result_init (int len); */ +void rexmpp_dns_result_free (rexmpp_dns_result_t *result); + +int rexmpp_dns_ctx_init (rexmpp_t *s); +void rexmpp_dns_ctx_cleanup (rexmpp_t *s); +void rexmpp_dns_ctx_deinit (rexmpp_t *s); +int rexmpp_dns_fds (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds); +struct timeval * rexmpp_dns_timeout (rexmpp_t *s, + struct timeval *max_tv, + struct timeval *tv); + +typedef void (*dns_query_cb_t) (rexmpp_t *s, void *ptr, rexmpp_dns_result_t *result); + +int rexmpp_dns_resolve (rexmpp_t *s, + const char *query, + int rrtype, + int rrclass, + void* ptr, + dns_query_cb_t callback); + +int rexmpp_dns_process (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds); + + #endif diff --git a/src/rexmpp_tcp.c b/src/rexmpp_tcp.c index 27c3ba4..a4d5018 100644 --- a/src/rexmpp_tcp.c +++ b/src/rexmpp_tcp.c @@ -6,7 +6,6 @@ @copyright MIT license. */ -#include <unbound.h> #include <netdb.h> #include <arpa/nameser.h> #include <sys/socket.h> @@ -19,17 +18,19 @@ #include <arpa/inet.h> #include <fcntl.h> +#include "rexmpp.h" #include "rexmpp_tcp.h" +#include "rexmpp_dns.h" -void rexmpp_dns_aaaa_cb (void *ptr, - int status, - struct ub_result *result) +void rexmpp_tcp_dns_aaaa_cb (rexmpp_t *s, + void *ptr, + rexmpp_dns_result_t *result) { + (void)s; rexmpp_tcp_conn_t *conn = ptr; - conn->resolver_status_v6 = status; conn->resolved_v6 = result; - if (status == 0 && ! result->bogus && result->havedata) { + if (result != NULL) { conn->resolution_v6 = REXMPP_CONN_RESOLUTION_SUCCESS; conn->addr_cur_v6 = -1; } else { @@ -37,14 +38,14 @@ void rexmpp_dns_aaaa_cb (void *ptr, } } -void rexmpp_dns_a_cb (void *ptr, - int status, - struct ub_result *result) +void rexmpp_tcp_dns_a_cb (rexmpp_t *s, + void *ptr, + rexmpp_dns_result_t *result) { + (void)s; rexmpp_tcp_conn_t *conn = ptr; - conn->resolver_status_v4 = status; conn->resolved_v4 = result; - if (status == 0 && ! result->bogus && result->havedata) { + if (result != NULL) { conn->resolution_v4 = REXMPP_CONN_RESOLUTION_SUCCESS; conn->addr_cur_v4 = -1; if (conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) { @@ -74,11 +75,11 @@ void rexmpp_tcp_cleanup (rexmpp_tcp_conn_t *conn) { conn->resolution_v6 = REXMPP_CONN_RESOLUTION_INACTIVE; } if (conn->resolved_v4 != NULL) { - ub_resolve_free(conn->resolved_v4); + rexmpp_dns_result_free(conn->resolved_v4); conn->resolved_v4 = NULL; } if (conn->resolved_v6 != NULL) { - ub_resolve_free(conn->resolved_v6); + rexmpp_dns_result_free(conn->resolved_v6); conn->resolved_v6 = NULL; } } @@ -99,8 +100,8 @@ 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, +rexmpp_tcp_conn_init (rexmpp_t *s, + rexmpp_tcp_conn_t *conn, const char *host, uint16_t port) { @@ -165,12 +166,11 @@ 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_ctx = resolver_ctx; - 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); + rexmpp_dns_resolve(s, host, 28, 1, + conn, rexmpp_tcp_dns_aaaa_cb); + rexmpp_dns_resolve(s, host, 1, 1, + conn, rexmpp_tcp_dns_a_cb); return REXMPP_CONN_IN_PROGRESS; } @@ -193,7 +193,8 @@ int rexmpp_tcp_conn_ipv6_available(rexmpp_tcp_conn_t *conn) { } rexmpp_tcp_conn_error_t -rexmpp_tcp_conn_proceed (rexmpp_tcp_conn_t *conn, +rexmpp_tcp_conn_proceed (rexmpp_t *s, + rexmpp_tcp_conn_t *conn, fd_set *read_fds, fd_set *write_fds) { @@ -222,9 +223,7 @@ 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) { - if (ub_poll(conn->resolver_ctx)) { - ub_process(conn->resolver_ctx); - } + rexmpp_dns_process(s, read_fds, write_fds); } if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_FAILURE && @@ -344,17 +343,15 @@ rexmpp_tcp_conn_proceed (rexmpp_tcp_conn_t *conn, } } -int rexmpp_tcp_conn_fds (rexmpp_tcp_conn_t *conn, +int rexmpp_tcp_conn_fds (rexmpp_t *s, + rexmpp_tcp_conn_t *conn, fd_set *read_fds, fd_set *write_fds) { int max_fd = 0, i; if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_WAITING || conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) { - max_fd = ub_fd(conn->resolver_ctx) + 1; - if (max_fd != 0) { - FD_SET(max_fd - 1, read_fds); - } + max_fd = rexmpp_dns_fds(s, read_fds, write_fds); } for (i = 0; i < REXMPP_TCP_MAX_CONNECTION_ATTEMPTS; i++) { if (conn->sockets[i] != -1) { @@ -367,12 +364,17 @@ int rexmpp_tcp_conn_fds (rexmpp_tcp_conn_t *conn, return max_fd; } -struct timeval *rexmpp_tcp_conn_timeout (rexmpp_tcp_conn_t *conn, +struct timeval *rexmpp_tcp_conn_timeout (rexmpp_t *s, + rexmpp_tcp_conn_t *conn, struct timeval *max_tv, struct timeval *tv) { struct timeval now; struct timeval *ret = max_tv; + if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_WAITING || + conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) { + ret = rexmpp_dns_timeout(s, 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 && diff --git a/src/rexmpp_tcp.h b/src/rexmpp_tcp.h index 1e13ca3..5a296cc 100644 --- a/src/rexmpp_tcp.h +++ b/src/rexmpp_tcp.h @@ -21,6 +21,9 @@ #include <sys/time.h> +#include "rexmpp.h" +#include "rexmpp_dns.h" + #define REXMPP_TCP_MAX_CONNECTION_ATTEMPTS 20 #define REXMPP_TCP_IPV6_DELAY_MS 50 #define REXMPP_TCP_CONN_DELAY_MS 250 @@ -70,19 +73,13 @@ struct rexmpp_tcp_connection { /** @brief A port we are connecting to. */ uint16_t port; - /** @brief Resolver context. */ - struct ub_ctx *resolver_ctx; - /** @brief Resolver error is stored here when - ::REXMPP_CONN_RESOLVER_ERROR is returned. */ - int resolver_error; - /** @brief State of A record resolution. */ enum rexmpp_tcp_conn_resolution_status resolution_v4; /** @brief Status of A record resolution, as returned by the resolver. */ int resolver_status_v4; /** @brief Resolved A records. */ - struct ub_result *resolved_v4; + rexmpp_dns_result_t *resolved_v4; /** @brief The AF_INET address number we are currently at. */ int addr_cur_v4; @@ -92,7 +89,7 @@ struct rexmpp_tcp_connection { resolver. */ int resolver_status_v6; /** @brief Resolved AAAA records. */ - struct ub_result *resolved_v6; + rexmpp_dns_result_t *resolved_v6; /** @brief The AF_INET6 address number we are currently at. */ int addr_cur_v6; @@ -112,28 +109,30 @@ struct rexmpp_tcp_connection { /** @brief Initiates a connection. + @param[in] s ::rexmpp @param[out] conn An allocated connection structure. - @param[in] resolver_ctx Resolver context to use. @param[in] host A host to connect to. This could be a domain name, or a textual representation of an IPv4 or an IPv6 address. @param[in] port A port to connect to. @returns A ::rexmpp_tcp_conn_error state. */ rexmpp_tcp_conn_error_t -rexmpp_tcp_conn_init (rexmpp_tcp_conn_t *conn, - struct ub_ctx *resolver_ctx, +rexmpp_tcp_conn_init (rexmpp_t *s, + rexmpp_tcp_conn_t *conn, const char *host, uint16_t port); /** @brief Continues a connection process. + @param[in] s ::rexmpp @param[in,out] conn An active connection structure. @param[in] read_fds File descriptors available for reading from. @param[in] write_fds File descriptors available for writing to. @returns A ::rexmpp_tcp_conn_error state. */ rexmpp_tcp_conn_error_t -rexmpp_tcp_conn_proceed (rexmpp_tcp_conn_t *conn, +rexmpp_tcp_conn_proceed (rexmpp_t *s, + rexmpp_tcp_conn_t *conn, fd_set *read_fds, fd_set *write_fds); @@ -158,6 +157,7 @@ int rexmpp_tcp_conn_finish (rexmpp_tcp_conn_t *conn); File descriptors are only added to an @c fd_set, so the ones it already contains will not be lost. + @param[in] s ::rexmpp @param[in] conn An active connection structure. @param[out] read_fds File descriptors a connection process is interested in reading from. @@ -165,19 +165,22 @@ int rexmpp_tcp_conn_finish (rexmpp_tcp_conn_t *conn); interested in writing to. @returns Maximum file descriptor number, plus 1. */ -int rexmpp_tcp_conn_fds (rexmpp_tcp_conn_t *conn, +int rexmpp_tcp_conn_fds (rexmpp_t *s, + rexmpp_tcp_conn_t *conn, fd_set *read_fds, fd_set *write_fds); /** @brief Reports timeouts. + @param[in] s ::rexmpp @param[in] conn An active connection structure. @param[in] max_tv An existing maximum timeout. @param[out] tv A timeval structure to store a new timeout in. @returns A pointer to either max_tv or tv, depending on which one is smaller. */ -struct timeval *rexmpp_tcp_conn_timeout (rexmpp_tcp_conn_t *conn, +struct timeval *rexmpp_tcp_conn_timeout (rexmpp_t *s, + rexmpp_tcp_conn_t *conn, struct timeval *max_tv, struct timeval *tv); |