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

View file

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

View file

@ -8,11 +8,6 @@
#include "libc/sysv/consts/af.h" #include "libc/sysv/consts/af.h"
#include "libc/sysv/errfuns.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. * 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, int ResolveHostsReverse(const struct HostsTxt *ht, int af, const uint8_t *ip,
char *buf, size_t bufsize) { 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 (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) v1 = *((uint32_t *)ip);
SortHostsTxt(ht, HOSTSTXT_SORTEDBYADDR); 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) { if (entry) {
strncpy(buf, &ht->strings.p[entry->name], bufsize); strncpy(buf, &ht->strings.p[entry->name], bufsize);
return 1; return 1;

View file

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

View file

@ -30,17 +30,6 @@ static int cmphoststxt(const struct HostsTxtEntry *e1,
return CompareDnsNames(&strings[e1->name], &strings[e2->name]); 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. * 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 * possible to efficiently search for subdomains, once the initial sort
* is done. * is done.
*/ */
void SortHostsTxt(struct HostsTxt *ht, int sort_by) { void SortHostsTxt(struct HostsTxt *ht) {
if (ht->entries.p) { if (ht->entries.p) {
if (sort_by == HOSTSTXT_SORTEDBYNAME) { qsort_r(ht->entries.p, ht->entries.i, sizeof(*ht->entries.p),
qsort_r(ht->entries.p, ht->entries.i, sizeof(*ht->entries.p), (void *)cmphoststxt, ht->strings.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;
}
} }
} }

View file

@ -48,7 +48,7 @@ TEST(ParseHostsTxt, testCorrectlyTokenizesAndSorts) {
ASSERT_EQ(1, fwrite(kInput, strlen(kInput), 1, f)); ASSERT_EQ(1, fwrite(kInput, strlen(kInput), 1, f));
rewind(f); rewind(f);
ASSERT_EQ(0, ParseHostsTxt(ht, f)); ASSERT_EQ(0, ParseHostsTxt(ht, f));
SortHostsTxt(ht, HOSTSTXT_SORTEDBYNAME); SortHostsTxt(ht);
ASSERT_EQ(4, ht->entries.i); 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].name]);
EXPECT_STREQ("cat.example.", &ht->strings.p[ht->entries.p[0].canon]); 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)); struct HostsTxt *ht = calloc(1, sizeof(struct HostsTxt));
FILE *f = fmemopen(kInput, strlen(kInput), "r+"); FILE *f = fmemopen(kInput, strlen(kInput), "r+");
ASSERT_EQ(0, ParseHostsTxt(ht, f)); ASSERT_EQ(0, ParseHostsTxt(ht, f));
SortHostsTxt(ht, HOSTSTXT_SORTEDBYNAME); SortHostsTxt(ht);
ASSERT_EQ(5, ht->entries.i); ASSERT_EQ(5, ht->entries.i);
EXPECT_STREQ("127.0.0.1", EzIp4Lookup(ht, "localhost")); EXPECT_STREQ("127.0.0.1", EzIp4Lookup(ht, "localhost"));
EXPECT_STREQ("203.0.113.1", EzIp4Lookup(ht, "lol")); EXPECT_STREQ("203.0.113.1", EzIp4Lookup(ht, "lol"));
@ -66,7 +66,7 @@ TEST(ResolveHostsTxt, testCanonicalize) {
struct HostsTxt *ht = calloc(1, sizeof(struct HostsTxt)); struct HostsTxt *ht = calloc(1, sizeof(struct HostsTxt));
FILE *f = fmemopen(kInput, strlen(kInput), "r+"); FILE *f = fmemopen(kInput, strlen(kInput), "r+");
ASSERT_EQ(0, ParseHostsTxt(ht, f)); ASSERT_EQ(0, ParseHostsTxt(ht, f));
SortHostsTxt(ht, HOSTSTXT_SORTEDBYNAME); SortHostsTxt(ht);
ASSERT_EQ(5, ht->entries.i); ASSERT_EQ(5, ht->entries.i);
EXPECT_STREQ("localhost", EzCanonicalize(ht, "localhost")); EXPECT_STREQ("localhost", EzCanonicalize(ht, "localhost"));
EXPECT_STREQ("lol.example.", EzCanonicalize(ht, "lol")); EXPECT_STREQ("lol.example.", EzCanonicalize(ht, "lol"));