Happy DNS for Objective-C

Overview

Happy DNS for Objective-C

@qiniu on weibo LICENSE Build Status GitHub release codecov Platform

用途

调用系统底层Dns解析库,可以使用114 等第三方dns解析,可以使用 Doh 协议的 Dns 解析方案,也可以集成dnspod等httpdns。另外也有丰富的hosts 域名配置。

安装

通过CocoaPods

pod "HappyDNS"

运行环境

使用方法

* 返回IP列表

*records = [dns queryRecords:@"www.qiniu.com"];; ">
 NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:[QNResolver systemResolver]];
[array addObject:[[QNResolver alloc] initWithAddress:@"119.29.29.29"]];
[array addObject:[QNDohResolver resolverWithServer:@"https://dns.alidns.com/dns-query"]];
QNDnsManager *dns = [[QNDnsManager alloc] init:array networkInfo:[QNNetworkInfo normal]];
NSArray 
   
     *records = [dns queryRecords:@"www.qiniu.com"];;

   

* url 请求,返回一个IP 替换URL 里的domain

NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:[QNResolver systemResolver]];
[array addObject:[[QNResolver alloc] initWithAddress:@"119.29.29.29"]];
QNDnsManager *dns = [[QNDnsManager alloc] init:array networkInfo:[QNNetworkInfo normal]];
NSURL *u = [[NSURL alloc] initWithString:@"rtmp://www.qiniu.com/abc?q=1"];
NSURL *u2 = [dns queryAndReplaceWithIP:u];
  • 兼容 getaddrinfo, 方便底层C代码接入
static QNDnsManager *dns = nil;
dns = [[QNDnsManager alloc] init:@[ [QNResolver systemResolver] ] networkInfo:nil];
[QNDnsManager setGetAddrInfoBlock:^NSArray *(NSString *host) {
        return [dns query:host];
    }];
struct addrinfo hints = {0};
struct addrinfo *ai = NULL;
int x = qn_getaddrinfo(host, "http", &hints, &ai);
qn_freeaddrinfo(ai); // 也可以用系统的freeaddrinfo, 代码一致,不过最好用这个

运行测试

$ xctool -workspace HappyDNS.xcworkspace -scheme "HappyDNS_Mac" -sdk macosx -configuration Release test -test-sdk macosx

指定测试

可以在单元测试上修改,熟悉使用


常见问题

  • 如果碰到其他编译错误,请参考 CocoaPods 的 troubleshooting
  • httpdns 在ios8 时不支持 nat64 模式下 IP 直接访问url,原因是 NSUrlConnection 不支持。无论是用http://119.29.29.29/d 还是http://[64:ff9b::771d:1d1d]/d 都不行,此时可以使用localdns方式。
  • 如果软件有国外的使用情况时,建议初始化程序采取这样的方式
QNDnsManager *dns;
if([QNDnsManager needHttpDns]){
    NSMutableArray *array = [[NSMutableArray alloc] init];
    [array addObject:[[QNResolver alloc] initWithAddress:@"119.29.29.29"]];
    [array addObject:[QNResolver systemResolver]];
    dns = [[QNDnsManager alloc] init:array networkInfo:[QNNetworkInfo normal]];
}else{
    NSMutableArray *array = [[NSMutableArray alloc] init];
    [array addObject:[QNResolver systemResolver]];
    [array addObject:[[QNResolver alloc] initWithAddress:@"8.8.8.8"]];
    dns = [[QNDnsManager alloc] init:array networkInfo:[QNNetworkInfo normal]];
}

代码贡献

详情参考代码提交指南

贡献记录

联系我们

  • 如果有什么问题,可以到问答社区提问,问答社区
  • 如果发现了bug, 欢迎提交 issue
  • 如果有功能需求,欢迎提交 issue
  • 如果要提交代码,欢迎提交 pull request
  • 欢迎关注我们的微信 微博,及时获取动态信息。

代码许可

The MIT License (MIT).详情见 License文件.

Comments
  • was mutated while being enumerated.   崩溃

    was mutated while being enumerated. 崩溃

    Bugly 统计,HappytDNS 导致 崩溃很频繁。

    NSGenericException *** Collection <__NSArrayM: 0x1513962d0> was mutated while being enumerated. 解析原始 0 CoreFoundation ___exceptionPreprocess + 124 1 libobjc.A.dylib objc_exception_throw + 56 2 CoreFoundation -[NSException name] 3 HappyDNS records2Ips + 208 4 HappyDNS -[QNDnsManager queryInternalWithDomain:] + 1472 5 HappyDNS -[QNDnsManager queryWithDomain:] + 228 6 Qiniu -[QNSessionManager sendRequest:withCompleteBlock:withProgressBlock:withCancelBlock:] + 944 7 libdispatch.dylib __dispatch_call_block_and_release + 24 8 libdispatch.dylib __dispatch_client_callout + 16 9 libdispatch.dylib __dispatch_root_queue_drain + 2140 10 libdispatch.dylib __dispatch_worker_thread3 + 112 11 libsystem_pthread.dylib _pthread_wqthread + 1092 12 libsystem_pthread.dylib start_wqthread + 4

    具体问题在 QNDnsManager.m 文件中, 对 queryInternalWithDomain 方法进行了异步调用,并且在@synchronized 块 中对 result 数组进行了更改,所以会导致崩溃, 建议在 records2Ips 方法中 的 for (QNRecord *r in records) 改为 for (QNRecord *r in [records copy]) 或者不要使用 for in 来进行循环。

    static NSArray *records2Ips(NSArray *records) {
        NSMutableArray *array = [[NSMutableArray alloc] init];
        for (QNRecord *r in records) {    // 此处使用 for in  遍历会有问题
            [array addObject:r.value];
        }
        return array;
    }
    
    - (NSArray *)queryInternalWithDomain:(QNDomain *)domain {
        if (domain.hostsFirst) {
            NSArray *ret = [_hosts query:domain networkInfo:_curNetwork];
            if (ret != nil && ret.count != 0) {
                return ret;
            }
        }
        NSMutableArray *result;
        @synchronized(_cache) {
            if ([_curNetwork isEqualToInfo:[QNNetworkInfo normal]] && [QNNetworkInfo isNetworkChanged]) {
                [_cache removeAllObjects];
                _resolverStatus = 0;
            } else {
                result = [_cache objectForKey:domain.domain];
                if (result != nil && result.count > 1) {
                    QNRecord *first = [result firstObject];
                    [result removeObjectAtIndex:0];    // 此处对 result 进行了修改
                    [result addObject:first];
                }
            }
        }
    
        if (result != nil && result.count > 0) {
            QNRecord *record = [result objectAtIndex:0];
            if (![record expired:[[NSDate date] timeIntervalSince1970]]) {
                return records2Ips(result);
            }
        }
    ...
    
    opened by dimsky 5
  • NSURLErrorDomain Code=-999,如何集成http请求?

    NSURLErrorDomain Code=-999,如何集成http请求?

    Hi,

    network failure: Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey=https://54.255.32.12/v1.0/report, NSErrorFailingURLKey=https://54.255.32.12/v1.0/report, _NSURLErrorRelatedURLSessionTaskErrorKey=(
        "LocalDataTask <6B1DA05D-25CB-4DA8-9368-A7CF0FC40CCD>.<7>"
    ), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <6B1DA05D-25CB-4DA8-9368-A7CF0FC40CCD>.<7>, NSLocalizedDescription=cancelled}
    

    我就是简单的替换了NSUurl,需要该如何才能在接下来的https请求生效呢,有没有集成http请求的demo呢?

    我看网上说需要将http请求中的header中的字段host改成原始的域名,但是尝试后也没有效果。

    question 
    opened by seaguest 3
  • app进入后台再进入前台,由_cache中得到的result始终是nil

    app进入后台再进入前台,由_cache中得到的result始终是nil

    @synchronized(_cache) {
            if ([_curNetwork isEqualToInfo:[QNNetworkInfo normal]] && [QNNetworkInfo isNetworkChanged]) {
                [_cache removeAllObjects];
                _resolverStatus = 0;
            } else {
                result = [_cache objectForKey:domain.domain];
            }
        }
    

    如题所述情况下,确认是走的else,得到的result是nil。并没有发现代码中有其他地方清cache

    opened by ghost 3
  • 分享happy-dns 配合 SDWebImage 的使用

    分享happy-dns 配合 SDWebImage 的使用

    1.先pod 'HappyDNS', '~> 0.1.1'到项目中;

    2.项目中使用QNDnsManager 返回ips; NSMutableArray *array = [[NSMutableArray alloc]init]; [array addObject:[QNResolver systemResolver]]; [array addObject:[[QNResolver alloc] initWithAddres:@"114.114.115.115"]]; QNDnsManager *dnsManager = [[QNDnsManager alloc] init:array networkInfo:[QNNetworkInfo normal]]; NSArray *ips = [dnsManager query:@"http://xxxx.com2.z0.glb.qiniucdn.com"];

    3.请求七牛图片时使用ip替换域名http://xxxx.com2.z0.glb.qiniucdn.com,并设置HTTPHeadField; [SDWebImageManager.sharedManager.imageDownloader setValue:@"http://xxxx.com2.z0.glb.qiniucdn.com" forHTTPHeaderField:@"Host"]; 注:自己封装请求图片时使用[request setValue: @"http://xxxx.com2.z0.glb.qiniucdn.com" forHTTPHeaderField:@"Host"];

    4.项目中因为图片还有其他来源,这里区分使用设置HTTPHeadField中Host; SDWebImageManager.sharedManager.imageDownloader.headersFilter = ^NSDictionary *(NSURL *url, NSDictionary *headers) { NSMutableDictionary *mutableHeaders = [headers mutableCopy]; [mutableHeaders removeObjectForKey:@"Host"]; //是否为ip格式 if ([url.host rh_isIp]) { [mutableHeaders setValue:@"xxxx.com2.z0.glb.qiniucdn.com" forKey:@"Host"]; } return mutableHeaders; };

    最后,谢谢longbai在此过程中提供的帮助,由于缺少相关文档,冒昧抛砖引玉,希望可以帮助到小伙伴们,欢迎一起交流!

    opened by iTA9178 3
  • 关于是否兼容 ipv6 的问题

    关于是否兼容 ipv6 的问题

    release 里写了全面兼容 ipv6,不过我对照这片文章过了一下几个兼容点时,其中有一点

    IPV4时只需要通过res_ninit进行初始化就可以获取,但是在IPV6环境下需要通过res_getservers()接口才能获取。

    在0.3.3.1版本的 setup_dns_server 里只有使用 res_ninit ,这样也可以兼容 ipv6 吗?

    多谢

    question 
    opened by dopcn 2
  • 注释错误

    注释错误

    QNDnsManager.h :135:14:

    /**
     *    设置底层 业务统计 如connect 回调使用的Callback
     *
     *    @param dns 回调用的dnsmanager
     */
    + (void)setIpStatusCallback:(QNIpStatusCallback)block;
    
    opened by zhao0 1
  • 在 QNGetAddrInfo.m 中导入系统库时的写法有点问题

    在 QNGetAddrInfo.m 中导入系统库时的写法有点问题

    导入系统库时"#include "string.h" " 这种写法是不规范的,应该修改为 "#include <string.h>",后面的两个也一样。 使用了第一种写法,如果有第三方库中定义了string.h 文件的话,两个库在一起很可能就会报错。

    当然,我在这里提这个问题正式因为我们在使用 grpc的时候遇到这个尴尬的问题。所以,为了以后同学能够更好的使用,希望你们能够采纳我的建议,修改掉代码里的这种用法。

    期待你们的回复

    opened by cgwangding 1
  • 如果DNS返回IPv6地址会不会有问题

    如果DNS返回IPv6地址会不会有问题

    除了这个 nsurlconnection 方法之外

    NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest
                        returningResponse:&response
                        error:&httpError];
    
    opened by dopcn 1
  • 怎么手动集成?

    怎么手动集成?

    因为我需要修改源代码,所以想手动集成,结果报错了。 Undefined symbols for architecture arm64: "_res_9_setservers", referenced from: _setup_dns_server in QNResolvUtil.o "_res_9_ninit", referenced from: +[QNResolver systemDnsServer] in QNResolver.o _setup_dns_server in QNResolvUtil.o "_res_9_getservers", referenced from: +[QNResolver systemDnsServer] in QNResolver.o "_res_9_ns_name_uncompress", referenced from: _query_ip_v4 in QNResolver.o "_res_9_ns_parserr", referenced from: _query_ip in QNTxtResolver.o _query_ip_v4 in QNResolver.o "_res_9_nquery", referenced from: _query_ip in QNTxtResolver.o _query_ip_v4 in QNResolver.o "_res_9_ns_initparse", referenced from: _query_ip in QNTxtResolver.o _query_ip_v4 in QNResolver.o "_res_9_ndestroy", referenced from: _query_ip in QNTxtResolver.o _query_ip_v4 in QNResolver.o +[QNResolver systemDnsServer] in QNResolver.o ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation)

    opened by dpc323 1
  • DNS解析后Response的Set-Cookie

    DNS解析后Response的Set-Cookie

    请求某一地址:http://super.bxr.im/b/goods?anonymous=0&anonymous_id=90668dbc-1ca4-4872-b43e-1fa7489f5d19&channel_id=1&xrk_is_share=0&token=f066ff5a574f17a85d359af574c22a02&f_source=app-index-tool-2&sso_id=3205906

    dns解析为:http://122.13.170.7/b/goods?anonymous=0&anonymous_id=90668dbc-1ca4-4872-b43e-1fa7489f5d19&channel_id=1&xrk_is_share=0&token=f066ff5a574f17a85d359af574c22a02&f_source=app-index-tool-2&sso_id=3205906 并设置请求头host:super.bxr.im

    请求成功,但是response的Set-Cookie,貌似没保存到。

    再请求:http://122.13.170.7/b/commission/3205906?t=1464576038824&ct_sso_id=3205906&ct_channel_id=1&ct_f_source=
    没有前一个请求的返回cookie,导致请求失败

    这个如何解决?

    help-wanted 
    opened by weiminghuaa 1
Releases(v1.0.2)
Owner
Qiniu Cloud
Connect Data, Redefine Value.
Qiniu Cloud
A conforming Objective-C WebSocket client library.

SocketRocket A conforming WebSocket (RFC 6455) client library for iOS, macOS and tvOS. Test results for SocketRocket here. You can compare to what mod

Facebook Incubator 9.4k Dec 27, 2022
Easy to use CFNetwork wrapper for HTTP requests, Objective-C, Mac OS X and iPhone

ASIHTTPRequest is an easy to use wrapper around the CFNetwork API that makes some of the more tedious aspects of communicating with web servers easier

Ben Copsey 5.8k Dec 14, 2022
ROAD – Rapid Objective-C Applications Development

A set of reusable components taking advantage of extra dimension Attribute-Oriented Programming adds. Components Core - support for attributes, reflec

EPAM Systems 54 Nov 19, 2022
FakeGithub is an iOS application written using Objective-C

FakeGithub FakeGithub is an iOS application written using Objective-C. Opensource this project for learning purpose. Hope this could be a little usefu

FakeCoder 5 Oct 12, 2022
DNS tunnel for iOS based off of Iodine

Purple Haze A DNS tunnel client for iOS based on Iodine. A paid Apple Developer account is required to build because of the entitlements needed for Ne

null 37 Dec 24, 2022
Gapo challenge happy coding ^^

Gapo Challenge Implement Notification List screen Demo on simulator Development Language: IDE: Xcode (version 13.2.1) iOS Deployment target: from vers

null 1 May 27, 2022
Be happy, take a happic: 📸

happic: 하루 한 컷의 사진과 키워드 분석이 알려주는 나의 행복, 해픽 30th THE SOPT APP JAM 프로젝트 기간 : 2021.07.02 ~ 2021.07.23 Team happic iOS Developers 이세진 윤수빈 강승현 lsj8706 devx

Team-happic: 14 Nov 26, 2022
JSPatch bridge Objective-C and Javascript using the Objective-C runtime. You can call any Objective-C class and method in JavaScript by just including a small engine. JSPatch is generally used to hotfix iOS App.

JSPatch 中文介绍 | 文档 | JSPatch平台 请大家不要自行接入 JSPatch,统一接入 JSPatch 平台,让热修复在一个安全和可控的环境下使用。原因详见 这里 JSPatch bridges Objective-C and JavaScript using the Object

bang 11.4k Jan 1, 2023
NTP library for Swift and Objective-C. Get the true time impervious to device clock changes.

TrueTime for Swift Make sure to check out our counterpart too: TrueTime, an NTP library for Android. NTP client for Swift. Calculate the time "now" im

Instacart 530 Jan 4, 2023
Soulful docs for Swift & Objective-C

jazzy is a command-line utility that generates documentation for Swift or Objective-C About Both Swift and Objective-C projects are supported. Instead

Realm 7.2k Jan 1, 2023
Modern thread-safe and type-safe key-value observing for Swift and Objective-C

Now Archived and Forked PMKVObserver will not be maintained in this repository going forward. Please use, create issues on, and make PRs to the fork o

Postmates Inc. 708 Jun 29, 2022
MisterFusion is Swift DSL for AutoLayout. It is the extremely clear, but concise syntax, in addition, can be used in both Swift and Objective-C. Support Safe Area and Size Class.

MisterFusion MisterFusion makes more easier to use AutoLayout in Swift & Objective-C code. Features Simple And Concise Syntax Use in Swift and Objecti

Taiki Suzuki 316 Nov 17, 2022
The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. Objective-C and Swift compatible.

The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. PureLayout extends UIView/NSView, NSArray, and NSLayoutConstrai

PureLayout 7.6k Jan 6, 2023
A Matcher Framework for Swift and Objective-C

Nimble Use Nimble to express the expected outcomes of Swift or Objective-C expressions. Inspired by Cedar. // Swift expect(1 + 1).to(equal(2)) expect(

Quick 4.6k Dec 31, 2022
The Swift (and Objective-C) testing framework.

Quick is a behavior-driven development framework for Swift and Objective-C. Inspired by RSpec, Specta, and Ginkgo. // Swift import Quick import Nimbl

Quick 9.6k Dec 31, 2022
SwiftyTimer allows you to instantly schedule delays and repeating timers using convenient closure syntax. It's time to get rid of Objective-C cruft.

SwiftyTimer Modern Swifty API for NSTimer SwiftyTimer allows you to instantly schedule delays and repeating timers using convenient closure syntax. It

Radek Pietruszewski 1.2k Dec 27, 2022
Catch Objective-C exceptions in Swift

ExceptionCatcher Catch Objective-C exceptions in Swift There are many Cocoa APIs that can throw exceptions that cannot be caught in Swift (NSKeyedUnar

Sindre Sorhus 98 Nov 23, 2022
💡 A light Swift wrapper around Objective-C Runtime

A light wrapper around Objective-C Runtime. What exactly is lumos? lumos as mentioned is a light wrapper around objective-c runtime functions to allow

Suyash Shekhar 139 Dec 19, 2022
Swift-friendly API for a set of powerful Objective C runtime functions.

ObjectiveKit ObjectiveKit provides a Swift friendly API for a set of powerful Objective C runtime functions. Usage To use ObjectiveKit: Import Objecti

Roy Marmelstein 850 Oct 25, 2022
TraceLog is a highly configurable, flexible, portable, and simple to use debug logging system for Swift and Objective-C applications running on Linux, macOS, iOS, watchOS, and tvOS.

Please star this github repository to stay up to date. TraceLog Introduction TraceLog is a highly configurable, flexible, portable, and simple to use

Tony Stone 52 Oct 28, 2022