QNConnectChecker.m 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //
  2. // QNConnectChecker.m
  3. // QiniuSDK_Mac
  4. //
  5. // Created by yangsen on 2021/1/8.
  6. // Copyright © 2021 Qiniu. All rights reserved.
  7. //
  8. #import "QNDefine.h"
  9. #import "QNLogUtil.h"
  10. #import "QNConfiguration.h"
  11. #import "QNSingleFlight.h"
  12. #import "QNConnectChecker.h"
  13. #import "QNUploadSystemClient.h"
  14. @interface QNConnectChecker()
  15. @end
  16. @implementation QNConnectChecker
  17. + (QNSingleFlight *)singleFlight {
  18. static QNSingleFlight *singleFlight = nil;
  19. static dispatch_once_t onceToken;
  20. dispatch_once(&onceToken, ^{
  21. singleFlight = [[QNSingleFlight alloc] init];
  22. });
  23. return singleFlight;
  24. }
  25. + (BOOL)isConnected:(QNUploadSingleRequestMetrics *)metrics {
  26. return metrics && ((NSHTTPURLResponse *)metrics.response).statusCode > 99;
  27. }
  28. + (QNUploadSingleRequestMetrics *)check {
  29. __block QNUploadSingleRequestMetrics *metrics = nil;
  30. dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
  31. [self check:^(QNUploadSingleRequestMetrics *metricsP) {
  32. metrics = metricsP;
  33. dispatch_semaphore_signal(semaphore);
  34. }];
  35. dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
  36. return metrics;
  37. }
  38. + (void)check:(void (^)(QNUploadSingleRequestMetrics *))complete {
  39. QNSingleFlight *singleFlight = [self singleFlight];
  40. kQNWeakSelf;
  41. [singleFlight perform:@"connect_check" action:^(QNSingleFlightComplete _Nonnull singleFlightComplete) {
  42. kQNStrongSelf;
  43. [self checkAllHosts:^(QNUploadSingleRequestMetrics *metrics) {
  44. singleFlightComplete(metrics, nil);
  45. }];
  46. } complete:^(id _Nullable value, NSError * _Nullable error) {
  47. if (complete) {
  48. complete(value);
  49. }
  50. }];
  51. }
  52. + (void)checkAllHosts:(void (^)(QNUploadSingleRequestMetrics *metrics))complete {
  53. __block int completeCount = 0;
  54. __block BOOL isCompleted = false;
  55. __block BOOL isConnected = false;
  56. kQNWeakSelf;
  57. NSArray *allHosts = [kQNGlobalConfiguration.connectCheckURLStrings copy];
  58. for (NSString *host in allHosts) {
  59. [self checkHost:host complete:^(QNUploadSingleRequestMetrics *metrics) {
  60. kQNStrongSelf;
  61. BOOL isHostConnected = [self isConnected:metrics];
  62. @synchronized (self) {
  63. completeCount += 1;
  64. }
  65. if (isHostConnected) {
  66. isConnected = YES;
  67. }
  68. if (isHostConnected || completeCount == allHosts.count) {
  69. @synchronized (self) {
  70. if (isCompleted) {
  71. QNLogInfo(@"== check all hosts has completed totalCount:%d completeCount:%d", allHosts.count, completeCount);
  72. return;
  73. } else {
  74. QNLogInfo(@"== check all hosts completed totalCount:%d completeCount:%d", allHosts.count, completeCount);
  75. isCompleted = true;
  76. }
  77. }
  78. complete(metrics);
  79. } else {
  80. QNLogInfo(@"== check all hosts not completed totalCount:%d completeCount:%d", allHosts.count, completeCount);
  81. }
  82. }];
  83. }
  84. }
  85. + (void)checkHost:(NSString *)host complete:(void (^)(QNUploadSingleRequestMetrics *metrics))complete {
  86. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
  87. request.URL = [NSURL URLWithString:host];
  88. request.HTTPMethod = @"HEAD";
  89. request.timeoutInterval = kQNGlobalConfiguration.connectCheckTimeout;
  90. QNUploadSystemClient *client = [[QNUploadSystemClient alloc] init];
  91. [client request:request connectionProxy:nil progress:nil complete:^(NSURLResponse *response, QNUploadSingleRequestMetrics * metrics, NSData * _Nullable data, NSError * error) {
  92. QNLogInfo(@"== checkHost:%@ responseInfo:%@", host, response);
  93. complete(metrics);
  94. }];
  95. }
  96. @end