Skip to content

Commit dded8a9

Browse files
committed
Make code more efficient and andd diagnostics
1 parent 18024cd commit dded8a9

2 files changed

Lines changed: 169 additions & 70 deletions

File tree

Source/NSHost.m

Lines changed: 150 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
#endif /* !_WIN32 */
5353

5454
// Temporary hack ... dusable new code because it seems to break CI
55-
#undef HAVE_RESOLV_H
55+
//#undef HAVE_RESOLV_H
5656

5757
#if defined(HAVE_RESOLV_H)
5858
#include <resolv.h>
@@ -75,12 +75,35 @@
7575
static NSMutableDictionary *_hostCache = nil;
7676
static id null = nil;
7777

78-
7978
/*
8079
* Max hostname length in line with RFC 1123
8180
*/
8281
#define GSMAXHOSTNAMELEN 255
8382

83+
static BOOL
84+
isName(const char *n)
85+
{
86+
if (NULL == n
87+
|| (isdigit(n[0]) && sscanf(n, "%*d.%*d.%*d.%*d") == 4)
88+
|| 0 != strchr(n, ':'))
89+
{
90+
return NO;
91+
}
92+
return YES;
93+
}
94+
95+
static const char *
96+
getName(NSString *str)
97+
{
98+
const char *n = [str UTF8String];
99+
100+
if (isName(n))
101+
{
102+
return n;
103+
}
104+
return NULL;
105+
}
106+
84107
/**
85108
* Return the current host name ... may change if we are using dhcp etc
86109
*/
@@ -195,6 +218,74 @@ - (id) _initWithAddress: (NSString*)name
195218

196219
#if defined(HAVE_GETADDRINFO) && defined(HAVE_RESOLV_H)
197220

221+
static unsigned
222+
getCNames(NSString *host, NSMutableSet *cnames)
223+
{
224+
unsigned char response[NS_PACKETSZ];
225+
extern int h_errno;
226+
const char *name;
227+
unsigned added = 0;
228+
int len;
229+
230+
if ([cnames member: host] != nil)
231+
{
232+
return 0;
233+
}
234+
if (NULL == (name = getName(host)))
235+
{
236+
return 0;
237+
}
238+
239+
/* Perform DNS query for CNAME records so that we can get
240+
* any name pointed to by this one.
241+
*/
242+
len = res_query(name, ns_c_in, ns_t_cname, response, sizeof(response));
243+
if (len < 0)
244+
{
245+
if (h_errno != NO_DATA)
246+
{
247+
herror(name);
248+
}
249+
}
250+
else
251+
{
252+
ns_msg msg;
253+
int count;
254+
int i;
255+
256+
ns_initparse(response, len, &msg);
257+
count = ns_msg_count(msg, ns_s_an);
258+
for (i = 0; i < count; i++)
259+
{
260+
ns_rr rr;
261+
262+
ns_parserr(&msg, ns_s_an, i, &rr);
263+
264+
// Check if the record is a CNAME
265+
if (ns_rr_type(rr) == ns_t_cname)
266+
{
267+
char cname[NS_MAXDNAME];
268+
269+
if (ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg),
270+
ns_rr_rdata(rr), cname, sizeof(cname)) < 0)
271+
{
272+
fprintf(stderr, "Failed to uncompress CNAME\n");
273+
continue;
274+
}
275+
NSDebugFLLog(@"NSHost", @"res_query for '%@' found '%s'",
276+
host, cname);
277+
[cnames addObject: [NSString stringWithUTF8String: cname]];
278+
added++;
279+
}
280+
}
281+
}
282+
if (0 == added)
283+
{
284+
NSDebugFLLog(@"NSHost", @"res_query for '%@' found no CNAMEs", host);
285+
}
286+
return added;
287+
}
288+
198289
- (id) _initWithKey: (NSString*)key
199290
{
200291
ENTER_POOL
@@ -205,6 +296,7 @@ - (id) _initWithKey: (NSString*)key
205296
struct addrinfo hints;
206297
struct addrinfo *tmp;
207298
int err;
299+
BOOL keyIsName;
208300

209301
memset(&hints, '\0', sizeof(hints));
210302
hints.ai_flags = AI_CANONNAME;
@@ -214,19 +306,27 @@ - (id) _initWithKey: (NSString*)key
214306
{
215307
[addresses unionSet: [hostClass _localAddresses]];
216308
ptr = "localhost";
309+
keyIsName = NO;
310+
}
311+
else
312+
{
313+
getCNames(key, names);
314+
ptr = [key UTF8String];
315+
keyIsName = isName(ptr);
217316
}
218317

219318
err = getaddrinfo(ptr, 0, &hints, &entry);
220319
if (err)
221320
{
222-
fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(err));
321+
fprintf(stderr, "getaddrinfo '%s' failed: %s\n", ptr, gai_strerror(err));
223322
entry = NULL;
224323
}
225324
for (tmp = entry; tmp != NULL; tmp = tmp->ai_next)
226325
{
227326
char ipstr[INET6_ADDRSTRLEN];
228327
char host[NI_MAXHOST];
229328
void *addr;
329+
NSString *a;
230330

231331
#pragma clang diagnostic push
232332
#pragma clang diagnostic ignored "-Wcast-align"
@@ -246,85 +346,71 @@ - (id) _initWithKey: (NSString*)key
246346
}
247347
#pragma clang diagnostic pop
248348
inet_ntop(tmp->ai_family, addr, ipstr, sizeof(ipstr));
249-
[addresses addObject: [NSString stringWithUTF8String: ipstr]];
250-
251-
/* Possibly a reverse lookup of the address will give us a different
252-
* result to our key (if the key was an address or an alias) so we
253-
* might be able to get a new name for the host.
254-
*/
255-
if (getnameinfo(tmp->ai_addr, tmp->ai_addrlen, host, sizeof(host),
256-
NULL, 0, NI_NAMEREQD) == 0)
257-
{
258-
[names addObject: [NSString stringWithUTF8String: host]];
259-
}
260-
261-
/* If we have a conaonical name for the host, use it.
262-
*/
263-
if (tmp->ai_canonname && *tmp->ai_canonname)
349+
a = [NSString stringWithUTF8String: ipstr];
350+
if (nil == [addresses member: a])
264351
{
265-
unsigned char response[NS_PACKETSZ];
266-
extern int h_errno;
267-
ns_msg msg;
268-
int count;
269-
int len;
270-
int i;
271-
NSString *n;
272-
273-
n = [NSString stringWithUTF8String: tmp->ai_canonname];
274-
[names addObject: n];
275-
276-
/* Perform DNS query for CNAME records so that we can get
277-
* any name pointed to by this one.
278-
*/
279-
len = res_query(tmp->ai_canonname, ns_c_in, ns_t_cname,
280-
response, sizeof(response));
281-
if (len < 0)
352+
[addresses addObject: a];
353+
354+
/* Possibly a reverse lookup of the address will give us a different
355+
* result to our key (if the key was an address or an alias) so we
356+
* might be able to get a new name for the host.
357+
*/
358+
if (getnameinfo(tmp->ai_addr, tmp->ai_addrlen, host, sizeof(host),
359+
NULL, 0, NI_NAMEREQD) == 0)
282360
{
283-
if (h_errno != NO_DATA)
361+
NSString *n = [NSString stringWithUTF8String: host];
362+
363+
NSDebugMLog(@"NSHost", @"getnameinfo for '%s' found '%s'",
364+
ipstr, host);
365+
if (nil == [names member: n])
284366
{
285-
herror("res_query");
367+
[names addObject: n];
368+
getCNames(n, names);
286369
}
287-
continue;
288370
}
289-
290-
ns_initparse(response, len, &msg);
291-
count = ns_msg_count(msg, ns_s_an);
292-
for (i = 0; i < count; i++)
371+
else
293372
{
294-
ns_rr rr;
373+
NSDebugMLog(@"NSHost", @"getnameinfo for '%s' found nothing",
374+
ipstr);
375+
*host = '\0';
376+
}
295377

296-
ns_parserr(&msg, ns_s_an, i, &rr);
378+
/* If we have a canonical name for the host, use it.
379+
*/
380+
if (tmp->ai_canonname && *tmp->ai_canonname
381+
&& strcmp(tmp->ai_canonname, host) != 0)
382+
{
383+
NSString *n = [NSString stringWithUTF8String: tmp->ai_canonname];
297384

298-
// Check if the record is a CNAME
299-
if (ns_rr_type(rr) == ns_t_cname)
385+
if (nil == [names member: n])
300386
{
301-
char cname[NS_MAXDNAME];
302-
303-
if (ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg),
304-
ns_rr_rdata(rr), cname, sizeof(cname)) < 0)
305-
{
306-
fprintf(stderr, "Failed to uncompress CNAME\n");
307-
continue;
308-
}
309-
[names addObject: [NSString stringWithUTF8String: cname]];
387+
[names addObject: n];
388+
getCNames(n, names);
310389
}
311390
}
312391
}
313392
}
314393
if (entry)
315394
{
316-
if (nil == [addresses member: key])
317-
{
318-
/* The key was not an address ... so it must be a host name
319-
*/
320-
[names addObject: key];
321-
}
322395
freeaddrinfo(entry);
323396
}
324397
if ([names count] || [addresses count])
325398
{
326-
_names = [names copy];
327399
_addresses = [addresses copy];
400+
if (keyIsName)
401+
{
402+
[names addObject: key];
403+
}
404+
if ([names count])
405+
{
406+
_names = [names copy];
407+
}
408+
else
409+
{
410+
/* No names, so we duplicate addresses as names
411+
*/
412+
_names = [_addresses copy];
413+
}
328414
}
329415
else
330416
{
@@ -490,7 +576,6 @@ + (NSHost*) currentHost
490576
+ (NSHost*) hostWithName: (NSString*)name
491577
{
492578
NSHost *host = nil;
493-
const char *n;
494579

495580
if (name == nil)
496581
{
@@ -506,9 +591,7 @@ + (NSHost*) hostWithName: (NSString*)name
506591
/* If this looks like an address rather than a host name ...
507592
* call the correct method instead of this one.
508593
*/
509-
n = [name UTF8String];
510-
if ((isdigit(n[0]) && sscanf(n, "%*d.%*d.%*d.%*d") == 4)
511-
|| 0 != strchr(n, ':'))
594+
if (NULL == getName(name))
512595
{
513596
return [self hostWithAddress: name];
514597
}
@@ -536,7 +619,7 @@ + (NSHost*) hostWithName: (NSString*)name
536619
{
537620
struct hostent *h;
538621

539-
h = gethostbyname((char*)n);
622+
h = gethostbyname((char*)[name UTF8String]);
540623
if (0 == h)
541624
{
542625
if ([name isEqualToString: myHostName()] == YES)

Tests/base/NSHost/create.m

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,51 @@
66
int main()
77
{
88
NSAutoreleasePool *arp = [NSAutoreleasePool new];
9+
NSString *s;
910
NSHost *current;
1011
NSHost *localh;
1112
NSHost *tmp;
1213

14+
tmp = [NSHost hostWithName: @"www.w3.org"];
15+
PASS(tmp != nil, "NSHost gets www.w3.org");
16+
NSLog(@"www.w3.org is %@", tmp);
17+
18+
tmp = [NSHost hostWithName: @"www.gnustep.org"];
19+
PASS(tmp != nil, "NSHost gets www.gnustep.org");
20+
NSLog(@"www.gnustep.org is %@", tmp);
21+
1322
current = [NSHost currentHost];
1423
PASS(current != nil && [current isKindOfClass: [NSHost class]],
1524
"NSHost understands +currentHost");
25+
NSLog(@"+currentHost is %@", current);
1626

1727
#if defined(GNUSTEP_BASE_LIBRARY)
1828
localh = [NSHost localHost];
1929
PASS(localh != nil && [localh isKindOfClass: [NSHost class]],
2030
"NSHost understands +localHost");
21-
NSLog(@"localHost: %@", localh);
31+
NSLog(@"+localHost is %@", localh);
2232
#else
2333
localh = current;
2434
#endif
2535

2636
tmp = [NSHost hostWithName: @"::1"];
2737
PASS([[tmp address] isEqual: @"::1"], "+hostWithName: works for IPV6 addr");
38+
NSLog(@"::1 is %@", tmp);
2839

29-
tmp = [NSHost hostWithName: [current name]];
40+
s = [current name];
41+
tmp = [NSHost hostWithName: s];
3042
PASS([tmp isEqualToHost: current], "NSHost understands +hostWithName:");
43+
NSLog(@"+hostWithName: %@ is %@", s, tmp);
3144

32-
tmp = [NSHost hostWithAddress: [current address]];
45+
s = [current address];
46+
tmp = [NSHost hostWithAddress: s];
3347
PASS([tmp isEqualToHost: current], "NSHost understands +hostWithAddress:");
48+
NSLog(@"+hostWithAddress: %@ is %@", s, tmp);
3449

3550
tmp = [NSHost hostWithName: @"127.0.0.1"];
3651
PASS(tmp != nil && [tmp isEqualToHost: localh],
3752
"NSHost understands [+hostWithName: 127.0.0.1]");
53+
NSLog(@"127.0.0.1 is %@", tmp);
3854

3955
[arp release]; arp = nil;
4056
return 0;

0 commit comments

Comments
 (0)