1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

async dns: add write confirm sul

If no routeable gateway, we can be unable to get WRITEABLE.  Add
a sul in the query to limit that situation to 3s before failing
the query.
This commit is contained in:
Andy Green 2021-02-02 17:16:08 +00:00
parent ed01fc2d44
commit 79c02baa9e
2 changed files with 46 additions and 10 deletions

View file

@ -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

View file

@ -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;