Simplify getnameinfo (#196)

The getnameinfo implementation requires an address -> name lookup on the
hosts file (ie struct HostsTxt) and the previous implementation used
flags to check whether HostsTxt was sorted according to address or name,
and then re-sorted it if necessary. Now getnameinfo lookup does not
require sorting, it does a simple linear lookup, and so the related code
was simplified

See #172 for discussion.
This commit is contained in:
Gautham 2021-06-23 01:05:58 +05:30 committed by GitHub
parent 1f87640d17
commit 98c53ae526
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 21 additions and 46 deletions

View file

@ -61,7 +61,6 @@ const struct HostsTxt *GetHostsTxt(void) {
init = &g_hoststxt_init;
if (!g_hoststxt) {
g_hoststxt = &init->ht;
init->ht.sorted_by = HOSTSTXT_NOT_SORTED;
init->ht.entries.n = pushpop(ARRAYLEN(init->entries));
init->ht.entries.p = init->entries;
init->ht.strings.n = pushpop(ARRAYLEN(init->strings));
@ -75,7 +74,7 @@ const struct HostsTxt *GetHostsTxt(void) {
/* TODO(jart): Elevate robustness. */
}
fclose(f);
SortHostsTxt(g_hoststxt, HOSTSTXT_SORTEDBYNAME);
SortHostsTxt(g_hoststxt);
}
return g_hoststxt;
}

View file

@ -21,12 +21,7 @@ struct HostsTxtStrings {
char *p;
};
#define HOSTSTXT_NOT_SORTED 0
#define HOSTSTXT_SORTEDBYNAME 1
#define HOSTSTXT_SORTEDBYADDR 2
struct HostsTxt {
int sorted_by;
struct HostsTxtEntries entries;
struct HostsTxtStrings strings;
};
@ -34,12 +29,12 @@ struct HostsTxt {
const struct HostsTxt *GetHostsTxt(void) returnsnonnull;
void FreeHostsTxt(struct HostsTxt **) paramsnonnull();
int ParseHostsTxt(struct HostsTxt *, FILE *) paramsnonnull();
void SortHostsTxt(struct HostsTxt *, int) paramsnonnull();
void SortHostsTxt(struct HostsTxt *) paramsnonnull();
int ResolveHostsTxt(const struct HostsTxt *, int, const char *,
struct sockaddr *, uint32_t, const char **)
paramsnonnull((1, 3));
int ResolveHostsReverse(const struct HostsTxt *, int, const uint8_t *, char *,
size_t);
size_t) paramsnonnull((1, 3));
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -8,11 +8,6 @@
#include "libc/sysv/consts/af.h"
#include "libc/sysv/errfuns.h"
static int hoststxtcmpaddr(const uint8_t *ip1, const struct HostsTxtEntry *he2) {
uint32_t v1 = *((uint32_t *)ip1), v2 = *((uint32_t *)he2->ip);
return (v1 == v2 ? 0 : (v1 > v2 ? 1 : -1));
}
/**
* Finds name associated with address in HOSTS.TXT table.
*
@ -27,15 +22,21 @@ static int hoststxtcmpaddr(const uint8_t *ip1, const struct HostsTxtEntry *he2)
*/
int ResolveHostsReverse(const struct HostsTxt *ht, int af, const uint8_t *ip,
char *buf, size_t bufsize) {
struct HostsTxtEntry *entry;
struct HostsTxtEntry *entry = NULL;
uint32_t v1, v2;
if (af != AF_INET && af != AF_UNSPEC) return eafnosupport();
if (!ht->entries.p) return -1;
if (!ht->entries.p || !buf || bufsize == 0) return -1;
if (ht->sorted_by != HOSTSTXT_SORTEDBYADDR)
SortHostsTxt(ht, HOSTSTXT_SORTEDBYADDR);
v1 = *((uint32_t *)ip);
for (size_t j = 0; j < ht->entries.i; j++) {
v2 = *((uint32_t *)ht->entries.p[j].ip);
if (v1 == v2) {
entry = &(ht->entries.p[j]);
break;
}
}
entry = bsearch(ip, ht->entries.p, ht->entries.i,
sizeof(struct HostsTxtEntry), (void *)hoststxtcmpaddr);
if (entry) {
strncpy(buf, &ht->strings.p[entry->name], bufsize);
return 1;

View file

@ -52,8 +52,6 @@ int ResolveHostsTxt(const struct HostsTxt *ht, int af, const char *name,
struct sockaddr_in *addr4;
struct HostsTxtEntry *entry;
if (af != AF_INET && af != AF_UNSPEC) return eafnosupport();
if (ht->sorted_by != HOSTSTXT_SORTEDBYNAME)
SortHostsTxt(ht, HOSTSTXT_SORTEDBYNAME);
if ((entry = bsearch_r(name, ht->entries.p, ht->entries.i,
sizeof(struct HostsTxtEntry), (void *)hoststxtgetcmp,
ht->strings.p))) {

View file

@ -30,17 +30,6 @@ static int cmphoststxt(const struct HostsTxtEntry *e1,
return CompareDnsNames(&strings[e1->name], &strings[e2->name]);
}
/**
* Compares addresses in HOSTS.TXT table.
* @see ResolveHostsReverse()
*/
static int cmphostsaddr(const struct HostsTxtEntry *e1,
const struct HostsTxtEntry *e2) {
if (e1 == e2) return 0;
uint32_t v1 = *((uint32_t *)e1->ip), v2 = *((uint32_t *)e2->ip);
return (v1 == v2 ? 0 : (v1 > v2 ? 1 : -1));
}
/**
* Sorts entries in HOSTS.TXT table.
*
@ -52,16 +41,9 @@ static int cmphostsaddr(const struct HostsTxtEntry *e1,
* possible to efficiently search for subdomains, once the initial sort
* is done.
*/
void SortHostsTxt(struct HostsTxt *ht, int sort_by) {
void SortHostsTxt(struct HostsTxt *ht) {
if (ht->entries.p) {
if (sort_by == HOSTSTXT_SORTEDBYNAME) {
qsort_r(ht->entries.p, ht->entries.i, sizeof(*ht->entries.p),
(void *)cmphoststxt, ht->strings.p);
ht->sorted_by = HOSTSTXT_SORTEDBYNAME;
} else {
qsort(ht->entries.p, ht->entries.i, sizeof(*ht->entries.p),
(void *)cmphostsaddr);
ht->sorted_by = HOSTSTXT_SORTEDBYADDR;
}
qsort_r(ht->entries.p, ht->entries.i, sizeof(*ht->entries.p),
(void *)cmphoststxt, ht->strings.p);
}
}

View file

@ -48,7 +48,7 @@ TEST(ParseHostsTxt, testCorrectlyTokenizesAndSorts) {
ASSERT_EQ(1, fwrite(kInput, strlen(kInput), 1, f));
rewind(f);
ASSERT_EQ(0, ParseHostsTxt(ht, f));
SortHostsTxt(ht, HOSTSTXT_SORTEDBYNAME);
SortHostsTxt(ht);
ASSERT_EQ(4, ht->entries.i);
EXPECT_STREQ("cat.example.", &ht->strings.p[ht->entries.p[0].name]);
EXPECT_STREQ("cat.example.", &ht->strings.p[ht->entries.p[0].canon]);

View file

@ -49,7 +49,7 @@ TEST(ResolveHostsTxt, testBasicLookups) {
struct HostsTxt *ht = calloc(1, sizeof(struct HostsTxt));
FILE *f = fmemopen(kInput, strlen(kInput), "r+");
ASSERT_EQ(0, ParseHostsTxt(ht, f));
SortHostsTxt(ht, HOSTSTXT_SORTEDBYNAME);
SortHostsTxt(ht);
ASSERT_EQ(5, ht->entries.i);
EXPECT_STREQ("127.0.0.1", EzIp4Lookup(ht, "localhost"));
EXPECT_STREQ("203.0.113.1", EzIp4Lookup(ht, "lol"));
@ -66,7 +66,7 @@ TEST(ResolveHostsTxt, testCanonicalize) {
struct HostsTxt *ht = calloc(1, sizeof(struct HostsTxt));
FILE *f = fmemopen(kInput, strlen(kInput), "r+");
ASSERT_EQ(0, ParseHostsTxt(ht, f));
SortHostsTxt(ht, HOSTSTXT_SORTEDBYNAME);
SortHostsTxt(ht);
ASSERT_EQ(5, ht->entries.i);
EXPECT_STREQ("localhost", EzCanonicalize(ht, "localhost"));
EXPECT_STREQ("lol.example.", EzCanonicalize(ht, "lol"));