mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 13:52:28 +00:00
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:
parent
1f87640d17
commit
98c53ae526
7 changed files with 21 additions and 46 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))) {
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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"));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue