QNResolver.m 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. //
  2. // QNResolver.m
  3. // HappyDNS
  4. //
  5. // Created by bailong on 15/6/23.
  6. // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved.
  7. //
  8. #include <arpa/inet.h>
  9. #include <resolv.h>
  10. #include <string.h>
  11. #include <netdb.h>
  12. #include <netinet/in.h>
  13. #include <netinet/in.h>
  14. #include <netinet/tcp.h>
  15. #include <unistd.h>
  16. #import "QNDomain.h"
  17. #import "QNIP.h"
  18. #import "QNRecord.h"
  19. #import "QNResolver.h"
  20. #import "QNResolvUtil.h"
  21. #if __IPHONE_OS_VERSION_MIN_REQUIRED
  22. #import <MobileCoreServices/MobileCoreServices.h>
  23. #import <UIKit/UIKit.h>
  24. #endif
  25. @interface QNResolver ()
  26. @property (nonatomic, readonly, strong) NSString *address;
  27. @property (nonatomic, readonly) NSUInteger timeout;
  28. @end
  29. static NSArray *query_ip_v4(res_state res, const char *host) {
  30. u_char answer[2000];
  31. int len = res_nquery(res, host, ns_c_in, ns_t_a, answer, sizeof(answer));
  32. ns_msg handle;
  33. ns_initparse(answer, len, &handle);
  34. int count = ns_msg_count(handle, ns_s_an);
  35. if (count <= 0) {
  36. res_ndestroy(res);
  37. return nil;
  38. }
  39. NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:count];
  40. char buf[32];
  41. char cnameBuf[NS_MAXDNAME];
  42. memset(cnameBuf, 0, sizeof(cnameBuf));
  43. for (int i = 0; i < count; i++) {
  44. ns_rr rr;
  45. if (ns_parserr(&handle, ns_s_an, i, &rr) != 0) {
  46. res_ndestroy(res);
  47. return nil;
  48. }
  49. int t = ns_rr_type(rr);
  50. int ttl = ns_rr_ttl(rr);
  51. NSString *val;
  52. if (t == ns_t_a) {
  53. const char *p = inet_ntop(AF_INET, ns_rr_rdata(rr), buf, sizeof(buf));
  54. val = [NSString stringWithUTF8String:p];
  55. } else if (t == ns_t_cname) {
  56. int x = ns_name_uncompress(answer, &(answer[len]), ns_rr_rdata(rr), cnameBuf, sizeof(cnameBuf));
  57. if (x <= 0) {
  58. continue;
  59. }
  60. val = [NSString stringWithUTF8String:cnameBuf];
  61. memset(cnameBuf, 0, sizeof(cnameBuf));
  62. } else {
  63. continue;
  64. }
  65. QNRecord *record = [[QNRecord alloc] init:val ttl:ttl type:t];
  66. [array addObject:record];
  67. }
  68. res_ndestroy(res);
  69. return array;
  70. }
  71. @implementation QNResolver
  72. - (instancetype)initWithAddres:(NSString *)address {
  73. return [self initWithAddress:address];
  74. }
  75. - (instancetype)initWithAddress:(NSString *)address {
  76. return [self initWithAddress:address timeout:QN_DNS_DEFAULT_TIMEOUT];
  77. }
  78. - (instancetype)initWithAddress:(NSString *)address
  79. timeout:(NSUInteger)time {
  80. if (self = [super init]) {
  81. _address = address;
  82. _timeout = time;
  83. }
  84. return self;
  85. }
  86. - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error {
  87. struct __res_state res;
  88. int r = setup_dns_server(&res, _address, _timeout);
  89. if (r != 0) {
  90. if (error != nil) {
  91. *error = [[NSError alloc] initWithDomain:@"qiniu.dns" code:kQNDomainSeverError userInfo:nil];
  92. }
  93. return nil;
  94. }
  95. NSArray *ret = query_ip_v4(&res, [domain.domain cStringUsingEncoding:NSUTF8StringEncoding]);
  96. if (ret != nil && ret.count != 0) {
  97. return ret;
  98. }
  99. if (error != nil) {
  100. *error = [[NSError alloc] initWithDomain:@"qiniu.dns" code:NSURLErrorDNSLookupFailed userInfo:nil];
  101. }
  102. return nil;
  103. }
  104. + (instancetype)systemResolver {
  105. return [[QNResolver alloc] initWithAddress:nil];
  106. }
  107. + (NSString *)systemDnsServer {
  108. struct __res_state res;
  109. int r = res_ninit(&res);
  110. if (r != 0) {
  111. return nil;
  112. }
  113. union res_sockaddr_union server[MAXNS] = {0};
  114. r = res_getservers(&res, server, MAXNS);
  115. res_ndestroy(&res);
  116. if (r <= 0) {
  117. return nil;
  118. }
  119. int family = server[0].sin.sin_family;
  120. char buf[64] = {0};
  121. const void *addr;
  122. if (family == AF_INET6) {
  123. addr = &server[0].sin6.sin6_addr;
  124. } else {
  125. addr = &server[0].sin.sin_addr;
  126. }
  127. const char *p = inet_ntop(family, addr, buf, sizeof(buf));
  128. if (p == NULL) {
  129. return nil;
  130. }
  131. return [NSString stringWithUTF8String:p];
  132. }
  133. @end