diff --git a/lib/system/async-dns/async-dns.c b/lib/system/async-dns/async-dns.c index d25c49b93..ac188b9de 100644 --- a/lib/system/async-dns/async-dns.c +++ b/lib/system/async-dns/async-dns.c @@ -34,7 +34,8 @@ static const lws_retry_bo_t retry_policy = { void lws_adns_q_destroy(lws_adns_q_t *q) { - lws_dll2_remove(&q->sul.list); + lws_sul_cancel(&q->sul); + lws_sul_cancel(&q->write_sul); lws_dll2_remove(&q->list); lws_free(q); } @@ -130,7 +131,13 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) int m, n, which; const char *name; - // lwsl_notice("%s: %p\n", __func__, q); + lwsl_notice("%s: %p\n", __func__, q); + + /* + * We managed to get to the point of being WRITEABLE, which is not a + * given if no routes. So call off the write_sul timeout for that. + */ + lws_sul_cancel(&q->write_sul); /* * UDP is not reliable, it can be locally dropped, or dropped @@ -232,7 +239,7 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) #endif /* if we did anything, check one more time */ - lws_callback_on_writable(wsi); +// lws_callback_on_writable(wsi); return; @@ -260,27 +267,27 @@ callback_async_dns(struct lws *wsi, enum lws_callback_reasons reason, /* callbacks related to raw socket descriptor */ case LWS_CALLBACK_RAW_ADOPT: - // lwsl_user("LWS_CALLBACK_RAW_ADOPT\n"); + lwsl_user("LWS_CALLBACK_RAW_ADOPT\n"); break; case LWS_CALLBACK_RAW_CLOSE: - // lwsl_user("LWS_CALLBACK_RAW_CLOSE\n"); + lwsl_user("LWS_CALLBACK_RAW_CLOSE\n"); break; case LWS_CALLBACK_RAW_RX: - // lwsl_user("LWS_CALLBACK_RAW_RX (%d)\n", (int)len); + lwsl_user("LWS_CALLBACK_RAW_RX (%d)\n", (int)len); // lwsl_hexdump_level(LLL_NOTICE, in, len); lws_adns_parse_udp(dns, in, len); break; case LWS_CALLBACK_RAW_WRITEABLE: - + lwsl_user("LWS_CALLBACK_RAW_WRITEABLE\n"); lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, dns->waiting.head) { lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, list); - if (lws_dll2_is_detached(&q->sul.list) && + if (//lws_dll2_is_detached(&q->sul.list) && (!q->asked || q->responded != q->asked)) lws_async_dns_writeable(wsi, q); } lws_end_foreach_dll_safe(d, d1); @@ -360,7 +367,7 @@ lws_adns_get_cache(lws_async_dns_t *dns, const char *name) lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, lws_dll2_get_head(&dns->cached)) { c = lws_container_of(d, lws_adns_cache_t, list); - cn = (const char *)&c[1]; + cn = lws_adns_cache_to_name(c); if (name && !c->incomplete && !strcasecmp(name, cn)) { /* Keep sorted by LRU: move to the head */ @@ -400,6 +407,24 @@ sul_cb_expire(struct lws_sorted_usec_list *sul) lws_adns_cache_destroy(c); } +void +sul_cb_write(struct lws_sorted_usec_list *sul) +{ + lws_adns_q_t *q = lws_container_of(sul, lws_adns_q_t, write_sul); + + lwsl_info("%s\n", __func__); + + /* + * Something's up, we couldn't even get from write request to + * WRITEABLE within the timeout, let alone the result... fail + * the query and everyone riding on it... + */ + + lwsl_info("%s: failing\n", __func__); + lws_async_dns_complete(q, NULL); + lws_adns_q_destroy(q); +} + void lws_async_dns_freeaddrinfo(const struct addrinfo **pai) { @@ -644,6 +669,8 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, } if (m == 4) { + ai = (struct addrinfo *)&c[1]; + sa46 = (lws_sockaddr46 *)&ai[1]; ai->ai_family = sa46->sa4.sin_family = AF_INET; ai->ai_addrlen = sizeof(sa46->sa4); ai->ai_addr = (struct sockaddr *)&sa46->sa4; @@ -737,6 +764,9 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, lws_async_dns_sul_cb_retry, &q->retry)) goto failed; + /* fail us if we can't write by this timeout */ + lws_sul_schedule(context, 0, &q->write_sul, sul_cb_write, LWS_US_PER_SEC); + /* * We may rewrite the copy at +sizeof(*q) for CNAME recursion. Keep * a second copy at + sizeof(*q) + DNS_MAX so we can create the cache diff --git a/lib/system/async-dns/private-lib-async-dns.h b/lib/system/async-dns/private-lib-async-dns.h index eafd4d000..bf1d3148b 100644 --- a/lib/system/async-dns/private-lib-async-dns.h +++ b/lib/system/async-dns/private-lib-async-dns.h @@ -45,15 +45,21 @@ typedef struct lws_adns_cache { uint8_t flags; /* b0 = has ipv4, b1 = has ipv6 */ char refcount; char incomplete; - /* name, and then result struct addrinfos overallocated here */ + /* addrinfo, lws_sa46, then name overallocated here */ } lws_adns_cache_t; +#define lws_adns_cache_to_name(_a) (((const char *)_a) + \ + sizeof(lws_adns_cache_t) + \ + sizeof(struct addrinfo) + \ + sizeof(lws_sockaddr46)) + /* * these objects are used while a query is ongoing... */ typedef struct { lws_sorted_usec_list_t sul; /* per-query write retry timer */ + lws_sorted_usec_list_t write_sul; /* fail if unable to write by this time */ lws_dll2_t list; lws_dll2_owner_t wsi_adns;