123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831 |
- //
- // QNHttpClient.m
- // AppTest
- //
- // Created by yangsen on 2020/4/7.
- // Copyright © 2020 com.qiniu. All rights reserved.
- //
- #import "QNErrorCode.h"
- #import "QNDefine.h"
- #import "QNCFHttpClient.h"
- #import "NSURLRequest+QNRequest.h"
- #import <sys/errno.h>
- @interface QNCFHttpClient()<NSStreamDelegate>
- @property(nonatomic, strong)NSMutableURLRequest *request;
- @property(nonatomic, assign)BOOL isReadResponseHeader;
- @property(nonatomic, assign)BOOL isInputStreamEvaluated;
- @property(nonatomic, strong)NSInputStream *inputStream;
- @property(nonatomic, strong)NSRunLoop *inputStreamRunLoop;
- // 上传进度
- @property(nonatomic, strong)NSTimer *progressTimer; // 进度定时器
- @property(nonatomic, assign)int64_t totalBytesSent; // 已上传大小
- @property(nonatomic, assign)int64_t totalBytesExpectedToSend; // 总大小
- @end
- @implementation QNCFHttpClient
- + (instancetype)client:(NSURLRequest *)request{
- if (!request) {
- return nil;
- }
-
- QNCFHttpClient *client = [[QNCFHttpClient alloc] init];
- [client setup:request];
- return client;
- }
- - (void)setup:(NSURLRequest *)request{
-
- @autoreleasepool {
- self.request = [request mutableCopy];
- NSInputStream *inputStream = [self createInputStream:self.request];
-
- NSString *host = [self.request qn_domain];
- if ([self.request qn_isHttps]) {
- [self setInputStreamSNI:inputStream sni:host];
- }
-
- [self setupProgress];
-
- self.inputStream = inputStream;
-
- }
- }
- - (void)startLoading{
- [self openInputStream];
- [self startProgress];
- }
- - (void)stopLoading{
-
- [self closeInputStream];
- [self endProgress:YES];
- }
- //MARK: -- request -> stream
- - (NSInputStream *)createInputStream:(NSURLRequest *)urlRequest{
-
- CFStringRef urlString = (__bridge CFStringRef) [urlRequest.URL absoluteString];
- CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault,
- urlString,
- NULL);
- CFStringRef httpMethod = (__bridge CFStringRef) urlRequest.HTTPMethod;
- CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault,
- httpMethod,
- url,
- kCFHTTPVersion1_1);
- CFRelease(url);
-
-
- NSDictionary *headFieldInfo = self.request.qn_allHTTPHeaderFields;
- for (NSString *headerField in headFieldInfo) {
- CFStringRef headerFieldP = (__bridge CFStringRef)headerField;
- CFStringRef headerFieldValueP = (__bridge CFStringRef)(headFieldInfo[headerField]);
- CFHTTPMessageSetHeaderFieldValue(request, headerFieldP, headerFieldValueP);
- }
-
- NSData *httpBody = [self.request qn_getHttpBody];
- if (httpBody) {
- CFDataRef bodyData = (__bridge CFDataRef) httpBody;
- CFHTTPMessageSetBody(request, bodyData);
- }
-
- CFReadStreamRef readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request);
- NSInputStream *inputStream = (__bridge_transfer NSInputStream *) readStream;
-
- CFRelease(request);
-
- return inputStream;
- }
- - (void)setInputStreamSNI:(NSInputStream *)inputStream sni:(NSString *)sni{
- if (!sni || sni.length == 0) {
- return;
- }
- NSMutableDictionary *settings = [NSMutableDictionary dictionary];
- [settings setObject:NSStreamSocketSecurityLevelNegotiatedSSL
- forKey:NSStreamSocketSecurityLevelKey];
- [settings setObject:sni
- forKey:(NSString *)kCFStreamSSLPeerName];
- [inputStream setProperty:settings forKey:(NSString *)CFBridgingRelease(kCFStreamPropertySSLSettings)];
- }
- //MARK: -- stream action
- - (void)openInputStream{
- if (!self.inputStreamRunLoop) {
- self.inputStreamRunLoop = [NSRunLoop currentRunLoop];
- }
- [self.inputStream scheduleInRunLoop:self.inputStreamRunLoop
- forMode:NSRunLoopCommonModes];
-
- self.inputStream.delegate = self;
- [self.inputStream open];
- }
- - (void)closeInputStream {
- [self.inputStream removeFromRunLoop:self.inputStreamRunLoop forMode:NSRunLoopCommonModes];
- [self.inputStream setDelegate:nil];
- [self.inputStream close];
- self.inputStream = nil;
- }
- - (BOOL)shouldEvaluateInputStreamServerTrust{
- if (![self.request qn_isHttps] || self.isInputStreamEvaluated) {
- return NO;
- } else {
- return YES;
- }
- }
- - (void)evaluateInputStreamServerTrust{
- if (self.isInputStreamEvaluated) {
- return;
- }
-
- SecTrustRef trust = (__bridge SecTrustRef) [self.inputStream propertyForKey:(__bridge NSString *) kCFStreamPropertySSLPeerTrust];
- NSString *host = [self.request allHTTPHeaderFields][@"host"];
- if ([self delegate_evaluateServerTrust:trust forDomain:host]) {
- self.isInputStreamEvaluated = YES;
- } else {
- [self delegate_onError:[NSError errorWithDomain:@"CFNetwork SSLHandshake failed"
- code:NSURLErrorSecureConnectionFailed
- userInfo:nil]];
- }
- }
- - (void)inputStreamGetAndNotifyHttpResponse{
- CFReadStreamRef readStream = (__bridge CFReadStreamRef)self.inputStream;
- CFHTTPMessageRef httpMessage = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader);
-
- CFDictionaryRef headerFields = CFHTTPMessageCopyAllHeaderFields(httpMessage);
- NSDictionary *headInfo = (__bridge_transfer NSDictionary *)headerFields;
-
- CFStringRef httpVersion = CFHTTPMessageCopyVersion(httpMessage);
- NSString *httpVersionInfo = (__bridge_transfer NSString *)httpVersion;
-
- CFIndex statusCode = CFHTTPMessageGetResponseStatusCode(httpMessage);
-
- if (![self isHttpRedirectStatusCode:statusCode]) {
- NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:self.request.URL statusCode:statusCode HTTPVersion:httpVersionInfo headerFields:headInfo];
- [self delegate_onReceiveResponse:response];
- }
-
- CFRelease(httpMessage);
- }
- - (void)inputStreamGetAndNotifyHttpData{
-
- UInt8 buffer[16 * 1024];
- UInt8 *buf = NULL;
- NSUInteger length = 0;
-
- if (![self.inputStream getBuffer:&buf length:&length]) {
- NSInteger amount = [self.inputStream read:buffer maxLength:sizeof(buffer)];
- buf = buffer;
- length = amount;
- }
-
- NSData *data = [[NSData alloc] initWithBytes:buf length:length];
- [self delegate_didLoadData:data];
- }
- - (void)inputStreamDidLoadHttpResponse{
-
- [self delegate_didFinish];
- }
- - (BOOL)isInputStreamHttpResponseHeaderComplete{
- CFReadStreamRef readStream = (__bridge CFReadStreamRef)self.inputStream;
- CFHTTPMessageRef responseMessage = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader);
- BOOL isComplete = CFHTTPMessageIsHeaderComplete(responseMessage);
- CFRelease(responseMessage);
- return isComplete;
- }
- - (BOOL)shouldInputStreamRedirect{
- CFReadStreamRef readStream = (__bridge CFReadStreamRef)self.inputStream;
- CFHTTPMessageRef responseMessage = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader);
- CFIndex statusCode = CFHTTPMessageGetResponseStatusCode(responseMessage);
- CFRelease(responseMessage);
- return [self isHttpRedirectStatusCode:statusCode];
- }
- - (BOOL)isHttpRedirectStatusCode:(NSInteger)code{
- if (code >= 300 && code < 400) {
- return YES;
- } else {
- return NO;
- }
- }
- - (void)inputStreamRedirect{
- CFReadStreamRef readStream = (__bridge CFReadStreamRef)self.inputStream;
- CFHTTPMessageRef responseMessage = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader);
-
- CFDictionaryRef headerFields = CFHTTPMessageCopyAllHeaderFields(responseMessage);
- NSDictionary *headInfo = (__bridge_transfer NSDictionary *)headerFields;
-
- NSString *urlString = headInfo[@"Location"];
- if (!urlString) {
- urlString = headInfo[@"location"];
- }
- if (!urlString) {
- return;
- }
-
- CFStringRef httpVersion = CFHTTPMessageCopyVersion(responseMessage);
- NSString *httpVersionString = (__bridge_transfer NSString *)httpVersion;
-
- CFIndex statusCode = CFHTTPMessageGetResponseStatusCode(responseMessage);
-
- NSURL *url = [NSURL URLWithString:urlString];
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
- request.HTTPMethod = @"GET";
- NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:self.request.URL
- statusCode:statusCode
- HTTPVersion:httpVersionString
- headerFields:headInfo];
-
- [self delegate_redirectedToRequest:request redirectResponse:response];
-
- CFRelease(responseMessage);
- }
- //MARK: -- NSStreamDelegate
- - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
- @autoreleasepool {
- switch (eventCode) {
- case NSStreamEventHasBytesAvailable:{
-
- if (![self isInputStreamHttpResponseHeaderComplete]) {
- break;
- }
-
- if ([self shouldEvaluateInputStreamServerTrust]) {
- [self evaluateInputStreamServerTrust];
- }
-
- if (self.isReadResponseHeader == NO) {
- self.isReadResponseHeader = YES;
- [self inputStreamGetAndNotifyHttpResponse];
- }
-
- [self inputStreamGetAndNotifyHttpData];
- }
- break;
- case NSStreamEventHasSpaceAvailable:
- break;
- case NSStreamEventErrorOccurred:{
- [self endProgress: YES];
- [self delegate_onError:[self translateCFNetworkErrorIntoUrlError:[self.inputStream streamError]]];
- [self closeInputStream];
- }
- break;
- case NSStreamEventEndEncountered:{
- if ([self shouldInputStreamRedirect]) {
- [self inputStreamRedirect];
- } else {
- [self endProgress: NO];
- [self inputStreamDidLoadHttpResponse];
- }
- }
- break;
- default:
- break;
- }
- }
- }
- //MARK: -- progress and timer action
- - (void)setupProgress{
- self.totalBytesExpectedToSend = [self.request.qn_getHttpBody length];
- }
- - (void)startProgress{
- [self createTimer];
- }
- - (void)endProgress:(BOOL)hasError{
-
- [self invalidateTimer];
-
- if (!hasError) {
- [self delegate_didSendBodyData:self.totalBytesExpectedToSend - self.totalBytesSent
- totalBytesSent:self.totalBytesExpectedToSend
- totalBytesExpectedToSend:self.totalBytesExpectedToSend];
- }
- }
- - (void)createTimer{
-
- if (_progressTimer) {
- [self invalidateTimer];
- }
-
- kQNWeakSelf;
- NSTimer *timer = [NSTimer timerWithTimeInterval:0.5
- target:weak_self
- selector:@selector(timerAction)
- userInfo:nil
- repeats:YES];
- [[NSRunLoop currentRunLoop] addTimer:timer
- forMode:NSDefaultRunLoopMode];
-
- [self timerAction];
- _progressTimer = timer;
- }
- - (void)invalidateTimer{
- [self.progressTimer invalidate];
- self.progressTimer = nil;
- }
- - (void)timerAction{
- long long totalBytesSent = [(NSNumber *)CFBridgingRelease(CFReadStreamCopyProperty((CFReadStreamRef)[self inputStream], kCFStreamPropertyHTTPRequestBytesWrittenCount)) longLongValue];
- long long bytesSent = totalBytesSent - self.totalBytesSent;
- self.totalBytesSent = totalBytesSent;
- if (bytesSent > 0 && self.totalBytesSent <= self.totalBytesSent) {
- [self delegate_didSendBodyData:bytesSent
- totalBytesSent:self.totalBytesSent
- totalBytesExpectedToSend:self.totalBytesExpectedToSend];
- }
- }
- - (NSError *)translateCFNetworkErrorIntoUrlError:(NSError *)cfError{
- if (cfError == nil) {
- return nil;
- }
-
- NSInteger errorCode = kQNNetworkError;
- NSString *errorInfo = [NSString stringWithFormat:@"cf client:[%ld] %@", (long)cfError.code, cfError.localizedDescription];
- switch (cfError.code) {
- case ENOENT: /* No such file or directory */
- errorCode = NSFileNoSuchFileError;
- break;
- case EIO: /* Input/output error */
- errorCode = kQNLocalIOError;
- break;
- case E2BIG: /* Argument list too long */
- break;
- case ENOEXEC: /* Exec format error */
- errorCode = kQNLocalIOError;
- break;
- case EBADF: /* Bad file descriptor */
- errorCode = kQNLocalIOError;
- break;
- case ECHILD: /* No child processes */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EDEADLK: /* Resource deadlock avoided */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ENOMEM: /* Cannot allocate memory */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EACCES: /* Permission denied */
- errorCode = NSURLErrorNoPermissionsToReadFile;
- break;
- case EFAULT: /* Bad address */
- errorCode = NSURLErrorBadURL;
- break;
- case EBUSY: /* Device / Resource busy */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EEXIST: /* File exists */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ENODEV: /* Operation not supported by device */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EISDIR: /* Is a directory */
- errorCode = NSURLErrorFileIsDirectory;
- break;
- case ENOTDIR: /* Not a directory */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EINVAL: /* Invalid argument */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ENFILE: /* Too many open files in system */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EMFILE: /* Too many open files */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EFBIG: /* File too large */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ENOSPC: /* No space left on device */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ESPIPE: /* Illegal seek */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EMLINK: /* Too many links */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EPIPE: /* Broken pipe */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EDOM: /* Numerical argument out of domain */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ERANGE: /* Result too large */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EAGAIN: /* Resource temporarily unavailable */
- break;
- case ENOTSOCK: /* Socket operation on non-socket */
- break;
- case EDESTADDRREQ: /* Destination address required */
- errorCode = NSURLErrorBadURL;
- break;
- case EMSGSIZE: /* Message too long */
- break;
- case EPROTOTYPE: /* Protocol wrong type for socket */
- break;
- case ENOPROTOOPT: /* Protocol not available */
- break;
- case EPROTONOSUPPORT: /* Protocol not supported */
- break;
- case ENOTSUP: /* Operation not supported */
- break;
- case EPFNOSUPPORT: /* Protocol family not supported */
- break;
- case EAFNOSUPPORT: /* Address family not supported by protocol family */
- break;
- case EADDRINUSE: /* Address already in use */
- break;
- case EADDRNOTAVAIL: /* Can't assign requested address */
- break;
- case ENETDOWN: /* Network is down */
- errorCode = NSURLErrorCannotConnectToHost;
- break;
- case ENETUNREACH: /* Network is unreachable */
- errorCode = NSURLErrorNetworkConnectionLost;
- break;
- case ENETRESET: /* Network dropped connection on reset */
- errorCode = NSURLErrorNetworkConnectionLost;
- break;
- case ECONNABORTED: /* Software caused connection abort */
- errorCode = NSURLErrorNetworkConnectionLost;
- break;
- case ECONNRESET: /* Connection reset by peer */
- errorCode = NSURLErrorNetworkConnectionLost;
- break;
- case ENOBUFS: /* No buffer space available */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EISCONN: /* Socket is already connected */
- break;
- case ENOTCONN: /* Socket is not connected */
- errorCode = NSURLErrorCannotConnectToHost;
- break;
- case ESHUTDOWN: /* Can't send after socket shutdown */
- break;
- case ETOOMANYREFS: /* Too many references: can't splice */
- break;
- case ETIMEDOUT: /* Operation timed out */
- errorCode = NSURLErrorTimedOut;
- break;
- case ECONNREFUSED: /* Connection refused */
- errorCode = NSURLErrorCannotConnectToHost;
- break;
- case ELOOP: /* Too many levels of symbolic links */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ENAMETOOLONG: /* File name too long */
- break;
- case EHOSTDOWN: /* Host is down */
- break;
- case EHOSTUNREACH: /* No route to host */
- break;
- case ENOTEMPTY: /* Directory not empty */
- break;
- case EPROCLIM: /* Too many processes */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EUSERS: /* Too many users */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EDQUOT: /* Disc quota exceeded */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ESTALE: /* Stale NFS file handle */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EREMOTE: /* Too many levels of remote in path */
- break;
- case EBADRPC: /* RPC struct is bad */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ERPCMISMATCH: /* RPC version wrong */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EPROGUNAVAIL: /* RPC prog. not avail */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EPROGMISMATCH: /* Program version wrong */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EPROCUNAVAIL: /* Bad procedure for program */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ENOLCK: /* No locks available */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ENOSYS: /* Function not implemented */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EFTYPE: /* Inappropriate file type or format */
- break;
- case EAUTH: /* Authentication error */
- break;
- case ENEEDAUTH: /* Need authenticator */
- break;
- case EPWROFF: /* Device power is off */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EDEVERR: /* Device error, e.g. paper out */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EOVERFLOW: /* Value too large to be stored in data type */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EBADEXEC: /* Bad executable */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EBADARCH: /* Bad CPU type in executable */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ESHLIBVERS: /* Shared library version mismatch */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EBADMACHO: /* Malformed Macho file */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case ECANCELED: /* Operation canceled */
- errorCode = NSURLErrorCancelled;
- break;
- case EIDRM: /* Identifier removed */
- break;
- case ENOMSG: /* No message of desired type */
- break;
- case EILSEQ: /* Illegal byte sequence */
- break;
- case ENOATTR: /* Attribute not found */
- break;
- case EBADMSG: /* Bad message */
- break;
- case EMULTIHOP: /* Reserved */
- break;
- case ENODATA: /* No message available on STREAM */
- break;
- case ENOLINK: /* Reserved */
- break;
- case ENOSR: /* No STREAM resources */
- break;
- case ENOSTR: /* Not a STREAM */
- break;
- case EPROTO: /* Protocol error */
- break;
- case ETIME: /* STREAM ioctl timeout */
- errorCode = NSURLErrorTimedOut;
- break;
- case EOPNOTSUPP: /* Operation not supported on socket */
- break;
- case ENOPOLICY: /* No such policy registered */
- break;
- case ENOTRECOVERABLE: /* State not recoverable */
- break;
- case EOWNERDEAD: /* Previous owner died */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case EQFULL: /* Interface output queue is full */
- break;
- case -9800: /* SSL protocol error */
- errorCode = NSURLErrorSecureConnectionFailed;
- break;
- case -9801: /* Cipher Suite negotiation failure */
- errorCode = NSURLErrorSecureConnectionFailed;
- break;
- case -9802: /* Fatal alert */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case -9803: /* I/O would block (not fatal) */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case -9804: /* attempt to restore an unknown session */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case -9805: /* connection closed gracefully */
- errorCode = NSURLErrorNetworkConnectionLost;
- break;
- case -9806: /* connection closed via error */
- errorCode = NSURLErrorNetworkConnectionLost;
- break;
- case -9807: /* invalid certificate chain */
- errorCode = NSURLErrorServerCertificateNotYetValid;
- break;
- case -9808: /* bad certificate format */
- errorCode = NSURLErrorServerCertificateNotYetValid;
- break;
- case -9809: /* underlying cryptographic error */
- errorCode = NSURLErrorSecureConnectionFailed;
- break;
- case -9810: /* Internal error */
- errorCode = NSURLErrorNotConnectedToInternet;
- break;
- case -9811: /* module attach failure */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case -9812: /* valid cert chain, untrusted root */
- errorCode = NSURLErrorServerCertificateHasUnknownRoot;
- break;
- case -9813: /* cert chain not verified by root */
- errorCode = NSURLErrorServerCertificateHasUnknownRoot;
- break;
- case -9814: /* chain had an expired cert */
- errorCode = NSURLErrorServerCertificateHasBadDate;
- break;
- case -9815: /* chain had a cert not yet valid */
- errorCode = NSURLErrorServerCertificateNotYetValid;
- break;
- case -9816: /* server closed session with no notification */
- errorCode = NSURLErrorNetworkConnectionLost;
- break;
- case -9817: /* insufficient buffer provided */
- errorCode = NSURLErrorCannotDecodeRawData;
- break;
- case -9818: /* bad SSLCipherSuite */
- errorCode = NSURLErrorClientCertificateRejected;
- break;
- case -9819: /* unexpected message received */
- errorCode = NSURLErrorNotConnectedToInternet;
- break;
- case -9820: /* bad MAC */
- errorCode = NSURLErrorNotConnectedToInternet;
- break;
- case -9821: /* decryption failed */
- errorCode = NSURLErrorNotConnectedToInternet;
- break;
- case -9822: /* record overflow */
- errorCode = NSURLErrorDataLengthExceedsMaximum;
- break;
- case -9823: /* decompression failure */
- errorCode = NSURLErrorDownloadDecodingFailedMidStream;
- break;
- case -9824: /* handshake failure */
- errorCode = NSURLErrorClientCertificateRejected;
- break;
- case -9825: /* misc. bad certificate */
- errorCode = NSURLErrorServerCertificateNotYetValid;
- break;
- case -9826: /* bad unsupported cert format */
- errorCode = NSURLErrorServerCertificateNotYetValid;
- break;
- case -9827: /* certificate revoked */
- errorCode = NSURLErrorServerCertificateNotYetValid;
- break;
- case -9828: /* certificate expired */
- errorCode = NSURLErrorServerCertificateNotYetValid;
- break;
- case -9829: /* unknown certificate */
- errorCode = NSURLErrorServerCertificateNotYetValid;
- break;
- case -9830: /* illegal parameter */
- errorCode = NSURLErrorCannotDecodeRawData;
- break;
- case -9831: /* unknown Cert Authority */
- errorCode = NSURLErrorServerCertificateNotYetValid;
- break;
- case -9832: /* access denied */
- errorCode = NSURLErrorClientCertificateRejected;
- break;
- case -9833: /* decoding error */
- errorCode = NSURLErrorServerCertificateNotYetValid;
- break;
- case -9834: /* decryption error */
- errorCode = NSURLErrorCannotDecodeRawData;
- break;
- case -9835: /* export restriction */
- errorCode = NSURLErrorCannotConnectToHost;
- break;
- case -9836: /* bad protocol version */
- errorCode = NSURLErrorCannotConnectToHost;
- break;
- case -9837: /* insufficient security */
- errorCode = NSURLErrorClientCertificateRejected;
- break;
- case -9838: /* internal error */
- errorCode = NSURLErrorTimedOut;
- break;
- case -9839: /* user canceled */
- errorCode = NSURLErrorCancelled;
- break;
- case -9840: /* no renegotiation allowed */
- errorCode = NSURLErrorCannotConnectToHost;
- break;
- case -9841: /* peer cert is valid, or was ignored if verification disabled */
- errorCode = NSURLErrorServerCertificateNotYetValid;
- break;
- case -9842: /* server has requested a client cert */
- errorCode = NSURLErrorClientCertificateRejected;
- break;
- case -9843: /* peer host name mismatch */
- errorCode = NSURLErrorNotConnectedToInternet;
- break;
- case -9844: /* peer dropped connection before responding */
- errorCode = NSURLErrorNetworkConnectionLost;
- break;
- case -9845: /* decryption failure */
- errorCode = NSURLErrorCannotDecodeRawData;
- break;
- case -9846: /* bad MAC */
- errorCode = NSURLErrorNotConnectedToInternet;
- break;
- case -9847: /* record overflow */
- errorCode = NSURLErrorDataLengthExceedsMaximum;
- break;
- case -9848: /* configuration error */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case -9849: /* unexpected (skipped) record in DTLS */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case -9850: /* weak ephemeral dh key */
- errorCode = kQNUnexpectedSysCallError;
- break;
- case -9851: /* SNI */
- errorCode = NSURLErrorClientCertificateRejected;
- break;
- default:
- break;
- }
-
- return [NSError errorWithDomain:NSURLErrorDomain code:errorCode userInfo:@{@"UserInfo" : errorInfo ?: @""}];
- }
- //MARK: -- delegate action
- - (void)delegate_redirectedToRequest:(NSURLRequest *)request
- redirectResponse:(NSURLResponse *)redirectResponse{
- if ([self.delegate respondsToSelector:@selector(redirectedToRequest:redirectResponse:)]) {
- [self.delegate redirectedToRequest:request redirectResponse:redirectResponse];
- }
- }
- - (BOOL)delegate_evaluateServerTrust:(SecTrustRef)serverTrust
- forDomain:(NSString *)domain{
- if ([self.delegate respondsToSelector:@selector(evaluateServerTrust:forDomain:)]) {
- return [self.delegate evaluateServerTrust:serverTrust forDomain:domain];
- } else {
- return NO;
- }
- }
- - (void)delegate_onError:(NSError *)error{
- if ([self.delegate respondsToSelector:@selector(onError:)]) {
- [self.delegate onError:error];
- }
- }
- - (void)delegate_didSendBodyData:(int64_t)bytesSent
- totalBytesSent:(int64_t)totalBytesSent
- totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
- if ([self.delegate respondsToSelector:@selector(didSendBodyData:
- totalBytesSent:
- totalBytesExpectedToSend:)]) {
- [self.delegate didSendBodyData:bytesSent
- totalBytesSent:totalBytesSent
- totalBytesExpectedToSend:totalBytesExpectedToSend];
- }
- }
- - (void)delegate_onReceiveResponse:(NSURLResponse *)response{
- if ([self.delegate respondsToSelector:@selector(onReceiveResponse:)]) {
- [self.delegate onReceiveResponse:response];
- }
- }
- - (void)delegate_didLoadData:(NSData *)data{
- if ([self.delegate respondsToSelector:@selector(didLoadData:)]) {
- [self.delegate didLoadData:data];
- }
- }
- - (void)delegate_didFinish{
- if ([self.delegate respondsToSelector:@selector(didFinish)]) {
- [self.delegate didFinish];
- }
- }
- @end
|