QNTxtResolver.m 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. //
  2. // QNTxtResolver.m
  3. // HappyDNS
  4. //
  5. // Created by bailong on 16/1/5.
  6. // Copyright © 2016年 Qiniu Cloud Storage. All rights reserved.
  7. //
  8. #import "QNTxtResolver.h"
  9. #include <arpa/inet.h>
  10. #include <resolv.h>
  11. #include <string.h>
  12. #include <netdb.h>
  13. #include <netinet/in.h>
  14. #include <netinet/in.h>
  15. #include <netinet/tcp.h>
  16. #include <unistd.h>
  17. #import "QNDomain.h"
  18. #import "QNRecord.h"
  19. #import "QNResolvUtil.h"
  20. #import "QNResolver.h"
  21. @interface QNTxtResolver ()
  22. @property (nonatomic, readonly, strong) NSString *address;
  23. @property (nonatomic, readonly) NSUInteger timeout;
  24. @end
  25. static NSArray *query_ip(res_state res, const char *host) {
  26. u_char answer[1500];
  27. int len = res_nquery(res, host, ns_c_in, ns_t_txt, answer, sizeof(answer));
  28. ns_msg handle;
  29. ns_initparse(answer, len, &handle);
  30. int count = ns_msg_count(handle, ns_s_an);
  31. if (count != 1) {
  32. res_ndestroy(res);
  33. return nil;
  34. }
  35. char txtbuf[256];
  36. memset(txtbuf, 0, sizeof(txtbuf));
  37. ns_rr rr;
  38. if (ns_parserr(&handle, ns_s_an, 0, &rr) != 0) {
  39. res_ndestroy(res);
  40. return nil;
  41. }
  42. int t = ns_rr_type(rr);
  43. int ttl = ns_rr_ttl(rr);
  44. int rdlen = ns_rr_rdlen(rr);
  45. if (rdlen <= 1 + 7) {
  46. res_ndestroy(res);
  47. return nil;
  48. }
  49. NSString *val;
  50. if (t == ns_t_txt) {
  51. memcpy(txtbuf, ns_rr_rdata(rr) + 1, rdlen - 1);
  52. val = [NSString stringWithUTF8String:txtbuf];
  53. } else {
  54. res_ndestroy(res);
  55. return nil;
  56. }
  57. NSArray *ipArray = [val componentsSeparatedByString:@","];
  58. NSMutableArray *ret = [[NSMutableArray alloc] initWithCapacity:ipArray.count];
  59. for (int i = 0; i < ipArray.count; i++) {
  60. QNRecord *record = [[QNRecord alloc] init:[ipArray objectAtIndex:i] ttl:ttl type:kQNTypeA];
  61. [ret addObject:record];
  62. }
  63. res_ndestroy(res);
  64. return ret;
  65. }
  66. @implementation QNTxtResolver
  67. - (instancetype)initWithAddress:(NSString *)address {
  68. return [self initWithAddress:address timeout:QN_DNS_DEFAULT_TIMEOUT];
  69. }
  70. - (instancetype)initWithAddress:(NSString *)address timeout:(NSUInteger)time {
  71. if (self = [super init]) {
  72. _address = address;
  73. _timeout = time;
  74. }
  75. return self;
  76. }
  77. - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error {
  78. struct __res_state res;
  79. int r = setup_dns_server(&res, _address, _timeout);
  80. if (r != 0) {
  81. if (error != nil) {
  82. *error = [[NSError alloc] initWithDomain:@"qiniu.dns" code:kQNDomainSeverError userInfo:nil];
  83. }
  84. return nil;
  85. }
  86. NSArray *ret = query_ip(&res, [domain.domain cStringUsingEncoding:NSUTF8StringEncoding]);
  87. if (ret == nil && error != nil) {
  88. *error = [[NSError alloc] initWithDomain:@"qiniu.dns" code:NSURLErrorDNSLookupFailed userInfo:nil];
  89. }
  90. return ret;
  91. }
  92. @end