QNCFHttpClient.m 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. //
  2. // QNHttpClient.m
  3. // AppTest
  4. //
  5. // Created by yangsen on 2020/4/7.
  6. // Copyright © 2020 com.qiniu. All rights reserved.
  7. //
  8. #import "QNErrorCode.h"
  9. #import "QNDefine.h"
  10. #import "QNCFHttpClient.h"
  11. #import "NSURLRequest+QNRequest.h"
  12. #import <sys/errno.h>
  13. @interface QNCFHttpClient()<NSStreamDelegate>
  14. @property(nonatomic, strong)NSMutableURLRequest *request;
  15. @property(nonatomic, assign)BOOL isReadResponseHeader;
  16. @property(nonatomic, assign)BOOL isInputStreamEvaluated;
  17. @property(nonatomic, strong)NSInputStream *inputStream;
  18. @property(nonatomic, strong)NSRunLoop *inputStreamRunLoop;
  19. // 上传进度
  20. @property(nonatomic, strong)NSTimer *progressTimer; // 进度定时器
  21. @property(nonatomic, assign)int64_t totalBytesSent; // 已上传大小
  22. @property(nonatomic, assign)int64_t totalBytesExpectedToSend; // 总大小
  23. @end
  24. @implementation QNCFHttpClient
  25. + (instancetype)client:(NSURLRequest *)request{
  26. if (!request) {
  27. return nil;
  28. }
  29. QNCFHttpClient *client = [[QNCFHttpClient alloc] init];
  30. [client setup:request];
  31. return client;
  32. }
  33. - (void)setup:(NSURLRequest *)request{
  34. @autoreleasepool {
  35. self.request = [request mutableCopy];
  36. NSInputStream *inputStream = [self createInputStream:self.request];
  37. NSString *host = [self.request qn_domain];
  38. if ([self.request qn_isHttps]) {
  39. [self setInputStreamSNI:inputStream sni:host];
  40. }
  41. [self setupProgress];
  42. self.inputStream = inputStream;
  43. }
  44. }
  45. - (void)startLoading{
  46. [self openInputStream];
  47. [self startProgress];
  48. }
  49. - (void)stopLoading{
  50. [self closeInputStream];
  51. [self endProgress:YES];
  52. }
  53. //MARK: -- request -> stream
  54. - (NSInputStream *)createInputStream:(NSURLRequest *)urlRequest{
  55. CFStringRef urlString = (__bridge CFStringRef) [urlRequest.URL absoluteString];
  56. CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault,
  57. urlString,
  58. NULL);
  59. CFStringRef httpMethod = (__bridge CFStringRef) urlRequest.HTTPMethod;
  60. CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault,
  61. httpMethod,
  62. url,
  63. kCFHTTPVersion1_1);
  64. CFRelease(url);
  65. NSDictionary *headFieldInfo = self.request.qn_allHTTPHeaderFields;
  66. for (NSString *headerField in headFieldInfo) {
  67. CFStringRef headerFieldP = (__bridge CFStringRef)headerField;
  68. CFStringRef headerFieldValueP = (__bridge CFStringRef)(headFieldInfo[headerField]);
  69. CFHTTPMessageSetHeaderFieldValue(request, headerFieldP, headerFieldValueP);
  70. }
  71. NSData *httpBody = [self.request qn_getHttpBody];
  72. if (httpBody) {
  73. CFDataRef bodyData = (__bridge CFDataRef) httpBody;
  74. CFHTTPMessageSetBody(request, bodyData);
  75. }
  76. CFReadStreamRef readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request);
  77. NSInputStream *inputStream = (__bridge_transfer NSInputStream *) readStream;
  78. CFRelease(request);
  79. return inputStream;
  80. }
  81. - (void)setInputStreamSNI:(NSInputStream *)inputStream sni:(NSString *)sni{
  82. if (!sni || sni.length == 0) {
  83. return;
  84. }
  85. NSMutableDictionary *settings = [NSMutableDictionary dictionary];
  86. [settings setObject:NSStreamSocketSecurityLevelNegotiatedSSL
  87. forKey:NSStreamSocketSecurityLevelKey];
  88. [settings setObject:sni
  89. forKey:(NSString *)kCFStreamSSLPeerName];
  90. [inputStream setProperty:settings forKey:(NSString *)CFBridgingRelease(kCFStreamPropertySSLSettings)];
  91. }
  92. //MARK: -- stream action
  93. - (void)openInputStream{
  94. if (!self.inputStreamRunLoop) {
  95. self.inputStreamRunLoop = [NSRunLoop currentRunLoop];
  96. }
  97. [self.inputStream scheduleInRunLoop:self.inputStreamRunLoop
  98. forMode:NSRunLoopCommonModes];
  99. self.inputStream.delegate = self;
  100. [self.inputStream open];
  101. }
  102. - (void)closeInputStream {
  103. [self.inputStream removeFromRunLoop:self.inputStreamRunLoop forMode:NSRunLoopCommonModes];
  104. [self.inputStream setDelegate:nil];
  105. [self.inputStream close];
  106. self.inputStream = nil;
  107. }
  108. - (BOOL)shouldEvaluateInputStreamServerTrust{
  109. if (![self.request qn_isHttps] || self.isInputStreamEvaluated) {
  110. return NO;
  111. } else {
  112. return YES;
  113. }
  114. }
  115. - (void)evaluateInputStreamServerTrust{
  116. if (self.isInputStreamEvaluated) {
  117. return;
  118. }
  119. SecTrustRef trust = (__bridge SecTrustRef) [self.inputStream propertyForKey:(__bridge NSString *) kCFStreamPropertySSLPeerTrust];
  120. NSString *host = [self.request allHTTPHeaderFields][@"host"];
  121. if ([self delegate_evaluateServerTrust:trust forDomain:host]) {
  122. self.isInputStreamEvaluated = YES;
  123. } else {
  124. [self delegate_onError:[NSError errorWithDomain:@"CFNetwork SSLHandshake failed"
  125. code:NSURLErrorSecureConnectionFailed
  126. userInfo:nil]];
  127. }
  128. }
  129. - (void)inputStreamGetAndNotifyHttpResponse{
  130. CFReadStreamRef readStream = (__bridge CFReadStreamRef)self.inputStream;
  131. CFHTTPMessageRef httpMessage = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader);
  132. CFDictionaryRef headerFields = CFHTTPMessageCopyAllHeaderFields(httpMessage);
  133. NSDictionary *headInfo = (__bridge_transfer NSDictionary *)headerFields;
  134. CFStringRef httpVersion = CFHTTPMessageCopyVersion(httpMessage);
  135. NSString *httpVersionInfo = (__bridge_transfer NSString *)httpVersion;
  136. CFIndex statusCode = CFHTTPMessageGetResponseStatusCode(httpMessage);
  137. if (![self isHttpRedirectStatusCode:statusCode]) {
  138. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:self.request.URL statusCode:statusCode HTTPVersion:httpVersionInfo headerFields:headInfo];
  139. [self delegate_onReceiveResponse:response];
  140. }
  141. CFRelease(httpMessage);
  142. }
  143. - (void)inputStreamGetAndNotifyHttpData{
  144. UInt8 buffer[16 * 1024];
  145. UInt8 *buf = NULL;
  146. NSUInteger length = 0;
  147. if (![self.inputStream getBuffer:&buf length:&length]) {
  148. NSInteger amount = [self.inputStream read:buffer maxLength:sizeof(buffer)];
  149. buf = buffer;
  150. length = amount;
  151. }
  152. NSData *data = [[NSData alloc] initWithBytes:buf length:length];
  153. [self delegate_didLoadData:data];
  154. }
  155. - (void)inputStreamDidLoadHttpResponse{
  156. [self delegate_didFinish];
  157. }
  158. - (BOOL)isInputStreamHttpResponseHeaderComplete{
  159. CFReadStreamRef readStream = (__bridge CFReadStreamRef)self.inputStream;
  160. CFHTTPMessageRef responseMessage = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader);
  161. BOOL isComplete = CFHTTPMessageIsHeaderComplete(responseMessage);
  162. CFRelease(responseMessage);
  163. return isComplete;
  164. }
  165. - (BOOL)shouldInputStreamRedirect{
  166. CFReadStreamRef readStream = (__bridge CFReadStreamRef)self.inputStream;
  167. CFHTTPMessageRef responseMessage = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader);
  168. CFIndex statusCode = CFHTTPMessageGetResponseStatusCode(responseMessage);
  169. CFRelease(responseMessage);
  170. return [self isHttpRedirectStatusCode:statusCode];
  171. }
  172. - (BOOL)isHttpRedirectStatusCode:(NSInteger)code{
  173. if (code >= 300 && code < 400) {
  174. return YES;
  175. } else {
  176. return NO;
  177. }
  178. }
  179. - (void)inputStreamRedirect{
  180. CFReadStreamRef readStream = (__bridge CFReadStreamRef)self.inputStream;
  181. CFHTTPMessageRef responseMessage = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader);
  182. CFDictionaryRef headerFields = CFHTTPMessageCopyAllHeaderFields(responseMessage);
  183. NSDictionary *headInfo = (__bridge_transfer NSDictionary *)headerFields;
  184. NSString *urlString = headInfo[@"Location"];
  185. if (!urlString) {
  186. urlString = headInfo[@"location"];
  187. }
  188. if (!urlString) {
  189. return;
  190. }
  191. CFStringRef httpVersion = CFHTTPMessageCopyVersion(responseMessage);
  192. NSString *httpVersionString = (__bridge_transfer NSString *)httpVersion;
  193. CFIndex statusCode = CFHTTPMessageGetResponseStatusCode(responseMessage);
  194. NSURL *url = [NSURL URLWithString:urlString];
  195. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  196. request.HTTPMethod = @"GET";
  197. NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:self.request.URL
  198. statusCode:statusCode
  199. HTTPVersion:httpVersionString
  200. headerFields:headInfo];
  201. [self delegate_redirectedToRequest:request redirectResponse:response];
  202. CFRelease(responseMessage);
  203. }
  204. //MARK: -- NSStreamDelegate
  205. - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
  206. @autoreleasepool {
  207. switch (eventCode) {
  208. case NSStreamEventHasBytesAvailable:{
  209. if (![self isInputStreamHttpResponseHeaderComplete]) {
  210. break;
  211. }
  212. if ([self shouldEvaluateInputStreamServerTrust]) {
  213. [self evaluateInputStreamServerTrust];
  214. }
  215. if (self.isReadResponseHeader == NO) {
  216. self.isReadResponseHeader = YES;
  217. [self inputStreamGetAndNotifyHttpResponse];
  218. }
  219. [self inputStreamGetAndNotifyHttpData];
  220. }
  221. break;
  222. case NSStreamEventHasSpaceAvailable:
  223. break;
  224. case NSStreamEventErrorOccurred:{
  225. [self endProgress: YES];
  226. [self delegate_onError:[self translateCFNetworkErrorIntoUrlError:[self.inputStream streamError]]];
  227. [self closeInputStream];
  228. }
  229. break;
  230. case NSStreamEventEndEncountered:{
  231. if ([self shouldInputStreamRedirect]) {
  232. [self inputStreamRedirect];
  233. } else {
  234. [self endProgress: NO];
  235. [self inputStreamDidLoadHttpResponse];
  236. }
  237. }
  238. break;
  239. default:
  240. break;
  241. }
  242. }
  243. }
  244. //MARK: -- progress and timer action
  245. - (void)setupProgress{
  246. self.totalBytesExpectedToSend = [self.request.qn_getHttpBody length];
  247. }
  248. - (void)startProgress{
  249. [self createTimer];
  250. }
  251. - (void)endProgress:(BOOL)hasError{
  252. [self invalidateTimer];
  253. if (!hasError) {
  254. [self delegate_didSendBodyData:self.totalBytesExpectedToSend - self.totalBytesSent
  255. totalBytesSent:self.totalBytesExpectedToSend
  256. totalBytesExpectedToSend:self.totalBytesExpectedToSend];
  257. }
  258. }
  259. - (void)createTimer{
  260. if (_progressTimer) {
  261. [self invalidateTimer];
  262. }
  263. kQNWeakSelf;
  264. NSTimer *timer = [NSTimer timerWithTimeInterval:0.5
  265. target:weak_self
  266. selector:@selector(timerAction)
  267. userInfo:nil
  268. repeats:YES];
  269. [[NSRunLoop currentRunLoop] addTimer:timer
  270. forMode:NSDefaultRunLoopMode];
  271. [self timerAction];
  272. _progressTimer = timer;
  273. }
  274. - (void)invalidateTimer{
  275. [self.progressTimer invalidate];
  276. self.progressTimer = nil;
  277. }
  278. - (void)timerAction{
  279. long long totalBytesSent = [(NSNumber *)CFBridgingRelease(CFReadStreamCopyProperty((CFReadStreamRef)[self inputStream], kCFStreamPropertyHTTPRequestBytesWrittenCount)) longLongValue];
  280. long long bytesSent = totalBytesSent - self.totalBytesSent;
  281. self.totalBytesSent = totalBytesSent;
  282. if (bytesSent > 0 && self.totalBytesSent <= self.totalBytesSent) {
  283. [self delegate_didSendBodyData:bytesSent
  284. totalBytesSent:self.totalBytesSent
  285. totalBytesExpectedToSend:self.totalBytesExpectedToSend];
  286. }
  287. }
  288. - (NSError *)translateCFNetworkErrorIntoUrlError:(NSError *)cfError{
  289. if (cfError == nil) {
  290. return nil;
  291. }
  292. NSInteger errorCode = kQNNetworkError;
  293. NSString *errorInfo = [NSString stringWithFormat:@"cf client:[%ld] %@", (long)cfError.code, cfError.localizedDescription];
  294. switch (cfError.code) {
  295. case ENOENT: /* No such file or directory */
  296. errorCode = NSFileNoSuchFileError;
  297. break;
  298. case EIO: /* Input/output error */
  299. errorCode = kQNLocalIOError;
  300. break;
  301. case E2BIG: /* Argument list too long */
  302. break;
  303. case ENOEXEC: /* Exec format error */
  304. errorCode = kQNLocalIOError;
  305. break;
  306. case EBADF: /* Bad file descriptor */
  307. errorCode = kQNLocalIOError;
  308. break;
  309. case ECHILD: /* No child processes */
  310. errorCode = kQNUnexpectedSysCallError;
  311. break;
  312. case EDEADLK: /* Resource deadlock avoided */
  313. errorCode = kQNUnexpectedSysCallError;
  314. break;
  315. case ENOMEM: /* Cannot allocate memory */
  316. errorCode = kQNUnexpectedSysCallError;
  317. break;
  318. case EACCES: /* Permission denied */
  319. errorCode = NSURLErrorNoPermissionsToReadFile;
  320. break;
  321. case EFAULT: /* Bad address */
  322. errorCode = NSURLErrorBadURL;
  323. break;
  324. case EBUSY: /* Device / Resource busy */
  325. errorCode = kQNUnexpectedSysCallError;
  326. break;
  327. case EEXIST: /* File exists */
  328. errorCode = kQNUnexpectedSysCallError;
  329. break;
  330. case ENODEV: /* Operation not supported by device */
  331. errorCode = kQNUnexpectedSysCallError;
  332. break;
  333. case EISDIR: /* Is a directory */
  334. errorCode = NSURLErrorFileIsDirectory;
  335. break;
  336. case ENOTDIR: /* Not a directory */
  337. errorCode = kQNUnexpectedSysCallError;
  338. break;
  339. case EINVAL: /* Invalid argument */
  340. errorCode = kQNUnexpectedSysCallError;
  341. break;
  342. case ENFILE: /* Too many open files in system */
  343. errorCode = kQNUnexpectedSysCallError;
  344. break;
  345. case EMFILE: /* Too many open files */
  346. errorCode = kQNUnexpectedSysCallError;
  347. break;
  348. case EFBIG: /* File too large */
  349. errorCode = kQNUnexpectedSysCallError;
  350. break;
  351. case ENOSPC: /* No space left on device */
  352. errorCode = kQNUnexpectedSysCallError;
  353. break;
  354. case ESPIPE: /* Illegal seek */
  355. errorCode = kQNUnexpectedSysCallError;
  356. break;
  357. case EMLINK: /* Too many links */
  358. errorCode = kQNUnexpectedSysCallError;
  359. break;
  360. case EPIPE: /* Broken pipe */
  361. errorCode = kQNUnexpectedSysCallError;
  362. break;
  363. case EDOM: /* Numerical argument out of domain */
  364. errorCode = kQNUnexpectedSysCallError;
  365. break;
  366. case ERANGE: /* Result too large */
  367. errorCode = kQNUnexpectedSysCallError;
  368. break;
  369. case EAGAIN: /* Resource temporarily unavailable */
  370. break;
  371. case ENOTSOCK: /* Socket operation on non-socket */
  372. break;
  373. case EDESTADDRREQ: /* Destination address required */
  374. errorCode = NSURLErrorBadURL;
  375. break;
  376. case EMSGSIZE: /* Message too long */
  377. break;
  378. case EPROTOTYPE: /* Protocol wrong type for socket */
  379. break;
  380. case ENOPROTOOPT: /* Protocol not available */
  381. break;
  382. case EPROTONOSUPPORT: /* Protocol not supported */
  383. break;
  384. case ENOTSUP: /* Operation not supported */
  385. break;
  386. case EPFNOSUPPORT: /* Protocol family not supported */
  387. break;
  388. case EAFNOSUPPORT: /* Address family not supported by protocol family */
  389. break;
  390. case EADDRINUSE: /* Address already in use */
  391. break;
  392. case EADDRNOTAVAIL: /* Can't assign requested address */
  393. break;
  394. case ENETDOWN: /* Network is down */
  395. errorCode = NSURLErrorCannotConnectToHost;
  396. break;
  397. case ENETUNREACH: /* Network is unreachable */
  398. errorCode = NSURLErrorNetworkConnectionLost;
  399. break;
  400. case ENETRESET: /* Network dropped connection on reset */
  401. errorCode = NSURLErrorNetworkConnectionLost;
  402. break;
  403. case ECONNABORTED: /* Software caused connection abort */
  404. errorCode = NSURLErrorNetworkConnectionLost;
  405. break;
  406. case ECONNRESET: /* Connection reset by peer */
  407. errorCode = NSURLErrorNetworkConnectionLost;
  408. break;
  409. case ENOBUFS: /* No buffer space available */
  410. errorCode = kQNUnexpectedSysCallError;
  411. break;
  412. case EISCONN: /* Socket is already connected */
  413. break;
  414. case ENOTCONN: /* Socket is not connected */
  415. errorCode = NSURLErrorCannotConnectToHost;
  416. break;
  417. case ESHUTDOWN: /* Can't send after socket shutdown */
  418. break;
  419. case ETOOMANYREFS: /* Too many references: can't splice */
  420. break;
  421. case ETIMEDOUT: /* Operation timed out */
  422. errorCode = NSURLErrorTimedOut;
  423. break;
  424. case ECONNREFUSED: /* Connection refused */
  425. errorCode = NSURLErrorCannotConnectToHost;
  426. break;
  427. case ELOOP: /* Too many levels of symbolic links */
  428. errorCode = kQNUnexpectedSysCallError;
  429. break;
  430. case ENAMETOOLONG: /* File name too long */
  431. break;
  432. case EHOSTDOWN: /* Host is down */
  433. break;
  434. case EHOSTUNREACH: /* No route to host */
  435. break;
  436. case ENOTEMPTY: /* Directory not empty */
  437. break;
  438. case EPROCLIM: /* Too many processes */
  439. errorCode = kQNUnexpectedSysCallError;
  440. break;
  441. case EUSERS: /* Too many users */
  442. errorCode = kQNUnexpectedSysCallError;
  443. break;
  444. case EDQUOT: /* Disc quota exceeded */
  445. errorCode = kQNUnexpectedSysCallError;
  446. break;
  447. case ESTALE: /* Stale NFS file handle */
  448. errorCode = kQNUnexpectedSysCallError;
  449. break;
  450. case EREMOTE: /* Too many levels of remote in path */
  451. break;
  452. case EBADRPC: /* RPC struct is bad */
  453. errorCode = kQNUnexpectedSysCallError;
  454. break;
  455. case ERPCMISMATCH: /* RPC version wrong */
  456. errorCode = kQNUnexpectedSysCallError;
  457. break;
  458. case EPROGUNAVAIL: /* RPC prog. not avail */
  459. errorCode = kQNUnexpectedSysCallError;
  460. break;
  461. case EPROGMISMATCH: /* Program version wrong */
  462. errorCode = kQNUnexpectedSysCallError;
  463. break;
  464. case EPROCUNAVAIL: /* Bad procedure for program */
  465. errorCode = kQNUnexpectedSysCallError;
  466. break;
  467. case ENOLCK: /* No locks available */
  468. errorCode = kQNUnexpectedSysCallError;
  469. break;
  470. case ENOSYS: /* Function not implemented */
  471. errorCode = kQNUnexpectedSysCallError;
  472. break;
  473. case EFTYPE: /* Inappropriate file type or format */
  474. break;
  475. case EAUTH: /* Authentication error */
  476. break;
  477. case ENEEDAUTH: /* Need authenticator */
  478. break;
  479. case EPWROFF: /* Device power is off */
  480. errorCode = kQNUnexpectedSysCallError;
  481. break;
  482. case EDEVERR: /* Device error, e.g. paper out */
  483. errorCode = kQNUnexpectedSysCallError;
  484. break;
  485. case EOVERFLOW: /* Value too large to be stored in data type */
  486. errorCode = kQNUnexpectedSysCallError;
  487. break;
  488. case EBADEXEC: /* Bad executable */
  489. errorCode = kQNUnexpectedSysCallError;
  490. break;
  491. case EBADARCH: /* Bad CPU type in executable */
  492. errorCode = kQNUnexpectedSysCallError;
  493. break;
  494. case ESHLIBVERS: /* Shared library version mismatch */
  495. errorCode = kQNUnexpectedSysCallError;
  496. break;
  497. case EBADMACHO: /* Malformed Macho file */
  498. errorCode = kQNUnexpectedSysCallError;
  499. break;
  500. case ECANCELED: /* Operation canceled */
  501. errorCode = NSURLErrorCancelled;
  502. break;
  503. case EIDRM: /* Identifier removed */
  504. break;
  505. case ENOMSG: /* No message of desired type */
  506. break;
  507. case EILSEQ: /* Illegal byte sequence */
  508. break;
  509. case ENOATTR: /* Attribute not found */
  510. break;
  511. case EBADMSG: /* Bad message */
  512. break;
  513. case EMULTIHOP: /* Reserved */
  514. break;
  515. case ENODATA: /* No message available on STREAM */
  516. break;
  517. case ENOLINK: /* Reserved */
  518. break;
  519. case ENOSR: /* No STREAM resources */
  520. break;
  521. case ENOSTR: /* Not a STREAM */
  522. break;
  523. case EPROTO: /* Protocol error */
  524. break;
  525. case ETIME: /* STREAM ioctl timeout */
  526. errorCode = NSURLErrorTimedOut;
  527. break;
  528. case EOPNOTSUPP: /* Operation not supported on socket */
  529. break;
  530. case ENOPOLICY: /* No such policy registered */
  531. break;
  532. case ENOTRECOVERABLE: /* State not recoverable */
  533. break;
  534. case EOWNERDEAD: /* Previous owner died */
  535. errorCode = kQNUnexpectedSysCallError;
  536. break;
  537. case EQFULL: /* Interface output queue is full */
  538. break;
  539. case -9800: /* SSL protocol error */
  540. errorCode = NSURLErrorSecureConnectionFailed;
  541. break;
  542. case -9801: /* Cipher Suite negotiation failure */
  543. errorCode = NSURLErrorSecureConnectionFailed;
  544. break;
  545. case -9802: /* Fatal alert */
  546. errorCode = kQNUnexpectedSysCallError;
  547. break;
  548. case -9803: /* I/O would block (not fatal) */
  549. errorCode = kQNUnexpectedSysCallError;
  550. break;
  551. case -9804: /* attempt to restore an unknown session */
  552. errorCode = kQNUnexpectedSysCallError;
  553. break;
  554. case -9805: /* connection closed gracefully */
  555. errorCode = NSURLErrorNetworkConnectionLost;
  556. break;
  557. case -9806: /* connection closed via error */
  558. errorCode = NSURLErrorNetworkConnectionLost;
  559. break;
  560. case -9807: /* invalid certificate chain */
  561. errorCode = NSURLErrorServerCertificateNotYetValid;
  562. break;
  563. case -9808: /* bad certificate format */
  564. errorCode = NSURLErrorServerCertificateNotYetValid;
  565. break;
  566. case -9809: /* underlying cryptographic error */
  567. errorCode = NSURLErrorSecureConnectionFailed;
  568. break;
  569. case -9810: /* Internal error */
  570. errorCode = NSURLErrorNotConnectedToInternet;
  571. break;
  572. case -9811: /* module attach failure */
  573. errorCode = kQNUnexpectedSysCallError;
  574. break;
  575. case -9812: /* valid cert chain, untrusted root */
  576. errorCode = NSURLErrorServerCertificateHasUnknownRoot;
  577. break;
  578. case -9813: /* cert chain not verified by root */
  579. errorCode = NSURLErrorServerCertificateHasUnknownRoot;
  580. break;
  581. case -9814: /* chain had an expired cert */
  582. errorCode = NSURLErrorServerCertificateHasBadDate;
  583. break;
  584. case -9815: /* chain had a cert not yet valid */
  585. errorCode = NSURLErrorServerCertificateNotYetValid;
  586. break;
  587. case -9816: /* server closed session with no notification */
  588. errorCode = NSURLErrorNetworkConnectionLost;
  589. break;
  590. case -9817: /* insufficient buffer provided */
  591. errorCode = NSURLErrorCannotDecodeRawData;
  592. break;
  593. case -9818: /* bad SSLCipherSuite */
  594. errorCode = NSURLErrorClientCertificateRejected;
  595. break;
  596. case -9819: /* unexpected message received */
  597. errorCode = NSURLErrorNotConnectedToInternet;
  598. break;
  599. case -9820: /* bad MAC */
  600. errorCode = NSURLErrorNotConnectedToInternet;
  601. break;
  602. case -9821: /* decryption failed */
  603. errorCode = NSURLErrorNotConnectedToInternet;
  604. break;
  605. case -9822: /* record overflow */
  606. errorCode = NSURLErrorDataLengthExceedsMaximum;
  607. break;
  608. case -9823: /* decompression failure */
  609. errorCode = NSURLErrorDownloadDecodingFailedMidStream;
  610. break;
  611. case -9824: /* handshake failure */
  612. errorCode = NSURLErrorClientCertificateRejected;
  613. break;
  614. case -9825: /* misc. bad certificate */
  615. errorCode = NSURLErrorServerCertificateNotYetValid;
  616. break;
  617. case -9826: /* bad unsupported cert format */
  618. errorCode = NSURLErrorServerCertificateNotYetValid;
  619. break;
  620. case -9827: /* certificate revoked */
  621. errorCode = NSURLErrorServerCertificateNotYetValid;
  622. break;
  623. case -9828: /* certificate expired */
  624. errorCode = NSURLErrorServerCertificateNotYetValid;
  625. break;
  626. case -9829: /* unknown certificate */
  627. errorCode = NSURLErrorServerCertificateNotYetValid;
  628. break;
  629. case -9830: /* illegal parameter */
  630. errorCode = NSURLErrorCannotDecodeRawData;
  631. break;
  632. case -9831: /* unknown Cert Authority */
  633. errorCode = NSURLErrorServerCertificateNotYetValid;
  634. break;
  635. case -9832: /* access denied */
  636. errorCode = NSURLErrorClientCertificateRejected;
  637. break;
  638. case -9833: /* decoding error */
  639. errorCode = NSURLErrorServerCertificateNotYetValid;
  640. break;
  641. case -9834: /* decryption error */
  642. errorCode = NSURLErrorCannotDecodeRawData;
  643. break;
  644. case -9835: /* export restriction */
  645. errorCode = NSURLErrorCannotConnectToHost;
  646. break;
  647. case -9836: /* bad protocol version */
  648. errorCode = NSURLErrorCannotConnectToHost;
  649. break;
  650. case -9837: /* insufficient security */
  651. errorCode = NSURLErrorClientCertificateRejected;
  652. break;
  653. case -9838: /* internal error */
  654. errorCode = NSURLErrorTimedOut;
  655. break;
  656. case -9839: /* user canceled */
  657. errorCode = NSURLErrorCancelled;
  658. break;
  659. case -9840: /* no renegotiation allowed */
  660. errorCode = NSURLErrorCannotConnectToHost;
  661. break;
  662. case -9841: /* peer cert is valid, or was ignored if verification disabled */
  663. errorCode = NSURLErrorServerCertificateNotYetValid;
  664. break;
  665. case -9842: /* server has requested a client cert */
  666. errorCode = NSURLErrorClientCertificateRejected;
  667. break;
  668. case -9843: /* peer host name mismatch */
  669. errorCode = NSURLErrorNotConnectedToInternet;
  670. break;
  671. case -9844: /* peer dropped connection before responding */
  672. errorCode = NSURLErrorNetworkConnectionLost;
  673. break;
  674. case -9845: /* decryption failure */
  675. errorCode = NSURLErrorCannotDecodeRawData;
  676. break;
  677. case -9846: /* bad MAC */
  678. errorCode = NSURLErrorNotConnectedToInternet;
  679. break;
  680. case -9847: /* record overflow */
  681. errorCode = NSURLErrorDataLengthExceedsMaximum;
  682. break;
  683. case -9848: /* configuration error */
  684. errorCode = kQNUnexpectedSysCallError;
  685. break;
  686. case -9849: /* unexpected (skipped) record in DTLS */
  687. errorCode = kQNUnexpectedSysCallError;
  688. break;
  689. case -9850: /* weak ephemeral dh key */
  690. errorCode = kQNUnexpectedSysCallError;
  691. break;
  692. case -9851: /* SNI */
  693. errorCode = NSURLErrorClientCertificateRejected;
  694. break;
  695. default:
  696. break;
  697. }
  698. return [NSError errorWithDomain:NSURLErrorDomain code:errorCode userInfo:@{@"UserInfo" : errorInfo ?: @""}];
  699. }
  700. //MARK: -- delegate action
  701. - (void)delegate_redirectedToRequest:(NSURLRequest *)request
  702. redirectResponse:(NSURLResponse *)redirectResponse{
  703. if ([self.delegate respondsToSelector:@selector(redirectedToRequest:redirectResponse:)]) {
  704. [self.delegate redirectedToRequest:request redirectResponse:redirectResponse];
  705. }
  706. }
  707. - (BOOL)delegate_evaluateServerTrust:(SecTrustRef)serverTrust
  708. forDomain:(NSString *)domain{
  709. if ([self.delegate respondsToSelector:@selector(evaluateServerTrust:forDomain:)]) {
  710. return [self.delegate evaluateServerTrust:serverTrust forDomain:domain];
  711. } else {
  712. return NO;
  713. }
  714. }
  715. - (void)delegate_onError:(NSError *)error{
  716. if ([self.delegate respondsToSelector:@selector(onError:)]) {
  717. [self.delegate onError:error];
  718. }
  719. }
  720. - (void)delegate_didSendBodyData:(int64_t)bytesSent
  721. totalBytesSent:(int64_t)totalBytesSent
  722. totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
  723. if ([self.delegate respondsToSelector:@selector(didSendBodyData:
  724. totalBytesSent:
  725. totalBytesExpectedToSend:)]) {
  726. [self.delegate didSendBodyData:bytesSent
  727. totalBytesSent:totalBytesSent
  728. totalBytesExpectedToSend:totalBytesExpectedToSend];
  729. }
  730. }
  731. - (void)delegate_onReceiveResponse:(NSURLResponse *)response{
  732. if ([self.delegate respondsToSelector:@selector(onReceiveResponse:)]) {
  733. [self.delegate onReceiveResponse:response];
  734. }
  735. }
  736. - (void)delegate_didLoadData:(NSData *)data{
  737. if ([self.delegate respondsToSelector:@selector(didLoadData:)]) {
  738. [self.delegate didLoadData:data];
  739. }
  740. }
  741. - (void)delegate_didFinish{
  742. if ([self.delegate respondsToSelector:@selector(didFinish)]) {
  743. [self.delegate didFinish];
  744. }
  745. }
  746. @end