Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -35,23 +35,33 @@ #import "OFUDPSocket.h" #ifdef OF_WINDOWS # import "OFWindowsRegistryKey.h" #endif +#import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFInvalidServerReplyException.h" #import "OFOpenItemFailedException.h" +#import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #import "OFResolveHostFailedException.h" #import "OFTruncatedDataException.h" #ifdef OF_WINDOWS # define interface struct # include # undef interface #endif + +#ifdef OF_AMIGAOS4 +# define __USE_INLINE__ +# define __NOLIBBASE__ +# define __NOGLOBALIFACE__ +# include +# include +#endif /* * RFC 1035 doesn't specify if pointers to pointers are allowed, and if so how * many. Since it's unspecified, we have to assume that it might happen, but we * also want to limit it to avoid DoS. Limiting it to 16 levels of pointers and @@ -65,18 +75,32 @@ #elif defined(OF_MORPHOS) # define HOSTS_PATH @"ENV:sys/net/hosts" # define RESOLV_CONF_PATH @"ENV:sys/net/resolv.conf" #elif defined(OF_AMIGAOS4) # define HOSTS_PATH @"DEVS:Internet/hosts" -# define RESOLV_CONF_PATH @"DEVS:Internet/resolv.conf" #elif defined(OF_AMIGAOS) # define HOSTS_PATH @"AmiTCP:db/hosts" # define RESOLV_CONF_PATH @"AmiTCP:db/resolv.conf" #else # define HOSTS_PATH @"/etc/hosts" # define RESOLV_CONF_PATH @"/etc/resolv.conf" #endif + +#ifdef OF_AMIGAOS4 +extern struct ExecIFace *IExec; +static struct Library *SocketBase = NULL; +static struct SocketIFace *ISocket = NULL; + +OF_DESTRUCTOR() +{ + if (ISocket != NULL) + DropInterface(ISocket); + + if (SocketBase != NULL) + CloseLibrary(SocketBase); +} +#endif /* * TODO: * * - Fallback to TCP @@ -129,22 +153,25 @@ context: (id)context; @end @interface OFDNSResolver () - (void)of_setDefaults; -- (void)of_parseConfig; +- (void)of_obtainSystemConfig; #ifdef OF_HAVE_FILES - (void)of_parseHosts: (OFString *)path; -# ifndef OF_WINDOWS +# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4) - (void)of_parseResolvConf: (OFString *)path; - (void)of_parseResolvConfOption: (OFString *)option; # endif #endif #ifdef OF_WINDOWS -- (void)of_parseNetworkParams; +- (void)of_obtainWindowsSystemConfig; +#endif +#ifdef OF_AMIGAOS4 +- (void)of_obtainAmigaOS4SystemConfig; #endif -- (void)of_reloadConfig; +- (void)of_reloadSystemConfig; - (void)of_resolveHost: (OFString *)host recordClass: (of_dns_resource_record_class_t)recordClass recordType: (of_dns_resource_record_type_t)recordType settings: (OFDNSResolverSettings *)settings nameServersIndex: (size_t)nameServersIndex @@ -709,10 +736,27 @@ @synthesize staticHosts = _staticHosts, nameServers = _nameServers; @synthesize localDomain = _localDomain, searchDomains = _searchDomains; @synthesize timeout = _timeout, maxAttempts = _maxAttempts; @synthesize minNumberOfDotsInAbsoluteName = _minNumberOfDotsInAbsoluteName; @synthesize usesTCP = _usesTCP, configReloadInterval = _configReloadInterval; + +#ifdef OF_AMIGAOS4 ++ (void)initialize +{ + if (self != [OFDNSResolver class]) + return; + + if ((SocketBase = OpenLibrary("bsdsocket.library", 4)) == NULL) + @throw [OFInitializationFailedException + exceptionWithClass: self]; + + if ((ISocket = (struct SocketIFace *) + GetInterface(SocketBase, "main", 1, NULL)) == NULL) + @throw [OFInitializationFailedException + exceptionWithClass: self]; +} +#endif + (instancetype)resolver { return [[[self alloc] init] autorelease]; } @@ -722,11 +766,11 @@ self = [super init]; @try { _queries = [[OFMutableDictionary alloc] init]; - [self of_parseConfig]; + [self of_obtainSystemConfig]; } @catch (id e) { [self release]; @throw e; } @@ -740,11 +784,11 @@ _minNumberOfDotsInAbsoluteName = 1; _usesTCP = false; _configReloadInterval = 2; } -- (void)of_parseConfig +- (void)of_obtainSystemConfig { void *pool = objc_autoreleasePoolPush(); #ifdef OF_WINDOWS OFString *path; #endif @@ -761,11 +805,14 @@ if (path != nil) [self of_parseHosts: path]; # endif - [self of_parseNetworkParams]; + [self of_obtainWindowsSystemConfig]; +#elif defined(OF_AMIGAOS4) + [self of_parseHosts: HOSTS_PATH]; + [self of_obtainAmigaOS4SystemConfig]; #elif defined(OF_HAVE_FILES) [self of_parseHosts: HOSTS_PATH]; # ifdef OF_OPENBSD [self of_parseHosts: @"/etc/resolv.conf.tail"]; # endif @@ -898,11 +945,11 @@ _staticHosts = [staticHosts copy]; objc_autoreleasePoolPop(pool); } -# ifndef OF_WINDOWS +# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4) - (void)of_parseResolvConf: (OFString *)path { void *pool = objc_autoreleasePoolPush(); OFCharacterSet *whitespaceCharacterSet = [OFCharacterSet whitespaceCharacterSet]; @@ -1010,16 +1057,14 @@ } # endif #endif #ifdef OF_WINDOWS -- (void)of_parseNetworkParams +- (void)of_obtainWindowsSystemConfig { - void *pool = objc_autoreleasePoolPush(); of_string_encoding_t encoding = [OFLocale encoding]; OFMutableArray *nameServers; - OFString *localDomain; /* * We need more space than FIXED_INFO in case we have more than one * name server, but we also want it to be properly aligned, meaning we * can't just get a buffer of bytes. Thus, we just get space for 8. */ @@ -1029,12 +1074,10 @@ if (GetNetworkParams(fixedInfo, &length) != ERROR_SUCCESS) return; nameServers = [OFMutableArray array]; - localDomain = [OFString stringWithCString: fixedInfo->DomainName - encoding: encoding]; for (iter = &fixedInfo->DnsServerList; iter != NULL; iter = iter->Next) [nameServers addObject: [OFString stringWithCString: iter->IpAddress.String encoding: encoding]]; @@ -1042,18 +1085,61 @@ if ([nameServers count] > 0) { [nameServers makeImmutable]; _nameServers = [nameServers copy]; } - if ([localDomain length] > 0) - _localDomain = [localDomain copy]; + if (fixedInfo->DomainName[0] != '\0') + _localDomain = [[OFString alloc] + initWithCString: fixedInfo->DomainName + encoding: encoding]; +} +#endif - objc_autoreleasePoolPop(pool); +#ifdef OF_AMIGAOS4 +- (void)of_obtainAmigaOS4SystemConfig +{ + OFMutableArray *nameServers = [OFMutableArray array]; + of_string_encoding_t encoding = [OFLocale encoding]; + struct List *nameServerList = ObtainDomainNameServerList(); + char buffer[MAXHOSTNAMELEN]; + + if (nameServerList == NULL) + @throw [OFOutOfMemoryException exception]; + + @try { + struct DomainNameServerNode *iter = + (struct DomainNameServerNode *)&nameServerList->lh_Head; + + while (iter->dnsn_MinNode.mln_Succ != NULL) { + if (iter->dnsn_UseCount != 0 && + iter->dnsn_Address != NULL) { + OFString *address = [OFString + stringWithCString: iter->dnsn_Address + encoding: encoding]; + + [nameServers addObject: address]; + } + + iter = (struct DomainNameServerNode *) + iter->dnsn_MinNode.mln_Succ; + } + } @finally { + ReleaseDomainNameServerList(nameServerList); + } + + if ([nameServers count] > 0) { + [nameServers makeImmutable]; + _nameServers = [nameServers copy]; + } + + if (GetDefaultDomainName(buffer, sizeof(buffer))) + _localDomain = [[OFString alloc] initWithCString: buffer + encoding: encoding]; } #endif -- (void)of_reloadConfig +- (void)of_reloadSystemConfig { /* * TODO: Rather than reparsing every, check what actually changed * (mtime) and only reset those. */ @@ -1077,11 +1163,11 @@ [self of_setDefaults]; [_lastConfigReload release]; _lastConfigReload = nil; - [self of_parseConfig]; + [self of_obtainSystemConfig]; } - (void)asyncResolveHost: (OFString *)host target: (id)target selector: (SEL)selector @@ -1108,11 +1194,11 @@ void *pool = objc_autoreleasePoolPush(); OFNumber *ID; OFString *domainName; OFDNSResolverQuery *query; - [self of_reloadConfig]; + [self of_reloadSystemConfig]; /* Random, unused ID */ do { ID = [OFNumber numberWithUInt16: (uint16_t)of_random()]; } while ([_queries objectForKey: ID] != nil); Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -83,16 +83,17 @@ { #ifdef OF_PSP int tid; #endif -#if defined(OF_OBJFW_RUNTIME) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4) +#if defined(OF_OBJFW_RUNTIME) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS) /* * This does not work on Win32 if ObjFW is built as a DLL. * - * On AmigaOS 4, atexit() calls objc_exit() before our destructors have - * run, but we need to send messages in some destructors. + * On AmigaOS, some destructors need to be able to send messages. + * Calling objc_exit() via atexit() would result in the runtime being + * destructed before for the destructors ran. */ atexit(objc_exit); #endif /* We need deterministic hashes for tests */