diff --git a/deps/cares/include/ares.h b/deps/cares/include/ares.h index 3d0f9cf97a07a7..3091064b5113b4 100644 --- a/deps/cares/include/ares.h +++ b/deps/cares/include/ares.h @@ -520,6 +520,8 @@ struct ares_txt_reply { struct ares_txt_reply *next; unsigned char *txt; size_t length; /* length excludes null termination */ + unsigned char record_start; /* 1 - if start of new record + * 0 - if a chunk in the same record */ }; struct ares_naptr_reply { diff --git a/deps/cares/src/ares_parse_txt_reply.c b/deps/cares/src/ares_parse_txt_reply.c index 981db4cd540d07..dabf73cd3f7998 100644 --- a/deps/cares/src/ares_parse_txt_reply.c +++ b/deps/cares/src/ares_parse_txt_reply.c @@ -133,8 +133,6 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen, break; } - ++strptr; - /* Allocate storage for this TXT answer appending it to the list */ txt_curr = ares_malloc_data(ARES_DATATYPE_TXT_REPLY); if (!txt_curr) @@ -152,6 +150,7 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen, } txt_last = txt_curr; + txt_curr->record_start = strptr == aptr; txt_curr->length = substr_len; txt_curr->txt = malloc (substr_len + 1/* Including null byte */); if (txt_curr->txt == NULL) @@ -159,6 +158,8 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen, status = ARES_ENOMEM; break; } + + ++strptr; memcpy ((char *) txt_curr->txt, strptr, substr_len); /* Make sure we NULL-terminate */ diff --git a/doc/api/dns.markdown b/doc/api/dns.markdown index b9b1502a234e43..211ac092b5aefa 100644 --- a/doc/api/dns.markdown +++ b/doc/api/dns.markdown @@ -95,8 +95,10 @@ attribute (e.g. `[{'priority': 10, 'exchange': 'mx.example.com'},...]`). ## dns.resolveTxt(hostname, callback) The same as `dns.resolve()`, but only for text queries (`TXT` records). -`addresses` is an array of the text records available for `hostname` (e.g., -`['v=spf1 ip4:0.0.0.0 ~all']`). +`addresses` is an 2-d array of the text records available for `hostname` (e.g., +`[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]`). Each sub-array contains TXT chunks of +one record. Depending on the use case, the could be either joined together or +treated separately. ## dns.resolveSrv(hostname, callback) diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index a7bfeda0fd0d1a..0f5987b01abb6a 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -576,12 +576,23 @@ class QueryTxtWrap: public QueryWrap { } Local txt_records = Array::New(env()->isolate()); + Local txt_chunk; ares_txt_reply* current = txt_out; - for (uint32_t i = 0; current != NULL; ++i, current = current->next) { + uint32_t i = 0; + for (uint32_t j = 0; current != NULL; current = current->next) { Local txt = OneByteString(env()->isolate(), current->txt); - txt_records->Set(i, txt); + // New record found - write out the current chunk + if (current->record_start) { + if (!txt_chunk.IsEmpty()) + txt_records->Set(i++, txt_chunk); + txt_chunk = Array::New(env()->isolate()); + j = 0; + } + txt_chunk->Set(j++, txt); } + // Push last chunk + txt_records->Set(i, txt_chunk); ares_free_data(txt_out);